`
kraft
  • 浏览: 18295 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

在GCC C程序中获取内存信息

    博客分类:
  • C
阅读更多
在GCC 中获取当前程序内存信息有几种手段
1 使用 mallinfo这个类
这部分code是直接抄来的,注意有很多项都是没用的,malloc 有两部分,一部分是使用sbrk申请的,不会还给系统,free过后会在total heap里,另一部分如果是大块内存申请的话会使用mmap
void getMemStatus()
{
    struct mallinfo info = mallinfo ();
    printf("arena = %d\n", info.arena);
    printf("ordblks = %d\n", info.ordblks);
    printf("smblks = %d\n", info.smblks);
    printf("hblks = %d\n", info.hblks);
    printf("hblkhd = %d\n", info.hblkhd);
    printf("usmblks = %d\n", info.usmblks);
    printf("fsmblks = %d\n", info.fsmblks);
    printf("uordblks = %d\n", info.uordblks);
    printf("fordblks = %d\n", info.fordblks);
    printf("keepcost = %d\n", info.keepcost);
}

Usage:


#include <malloc.h>

struct mallinfo [Data Type]
This structure type is used to return information about the dynamic memory allocator.
It contains the following members:
int arena
    This is the total size of memory allocated with sbrk by malloc, in bytes.
int ordblks
    This is the number of chunks not in use. (The memory allocator internally gets chunks of memory from the operating system, and then carves them up to satisfy individual malloc requests; see Section 3.2.2.6 [Eciency Considerations for malloc], page 36.)
int smblks
    This field is unused.
int hblks
    This is the total number of chunks allocated with mmap.
int hblkhd
    This is the total size of memory allocated with mmap, in bytes.
int usmblks
    This field is unused.
int fsmblks
    This field is unused.
int uordblks
    This is the total size of memory occupied by chunks handed out by malloc.
int fordblks
    This is the total size of memory occupied by free (not in use) chunks.
int keepcost
    This is the size of the top-most releasable chunk that normally borders the end of the heap (i.e., the high end of the virtual address space''s data segment).
struct mallinfo mallinfo (void) [Function]
    This function returns information about the current dynamic memory usage in a structure of type struct mallinfo.

2 使用mtrace
这个是GCC使用memory hook做的一个简单例子,在使用前需要设置环境变量MALLOC_TRACE,指向一个Log文件。check完后call muntrace或等待程序结束。
遗憾的是不能检查c++的,只看到了libstdc++.so
#include <stdio.h>
#include <error.h>
#include <mcheck.h>
int main(void){
    setenv("MALLOC_TRACE", "log", 1);   //设置环境变量MALLOC_TRACE
    mtrace();   //在需要检测的代码段之前调用mtrace函数
    char *str1 = (char*)malloc(10);
     char *str2 = (char*)malloc(10);
    free(str1);
    muntrace();    //在需要检测的代码段之后调用muntrace函数
    return 0;
}
跑完了使用gcc提供的perl写的工具mtrace来看,里面主要是使用了addr2line.
3 使用memory hook
如果有特殊要求,可以不用mtrace,直接用memory hook来干活,code还是copy过来的
主要是给几个全局函数指针赋值。下面的code有点啰嗦,不过不想改了,为了防止递归调用在自己的mhook里面要把malloc_hook恢复,其实只要置为null就行,malloc后置为自己的hook, 这个地方没有考虑多thread。
/* Prototypes for __malloc_hook, __free_hook */
#include <malloc.h>
#include <stdlib.h>
/* Prototypes for our hooks.  */

     static void my_init_hook (void);
     static void *my_malloc_hook (size_t, const void *);
     static void my_free_hook (void*, const void *);

     static void *(*old_malloc_hook) (size_t __size, __const __malloc_ptr_t);
     static void (*old_free_hook)  (void *__ptr, __const __malloc_ptr_t);
                   
/* Override initializing hook from the C library. */
void (*__malloc_initialize_hook) (void) = my_init_hook;

static void my_init_hook (void)
{
    old_malloc_hook = __malloc_hook;
    old_free_hook = __free_hook;
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
}
    
     static void *
          my_malloc_hook (size_t size, const void *caller)
{
    void *result;
    /* Restore all old hooks */
    __malloc_hook = old_malloc_hook;
    __free_hook = old_free_hook;
    /* Call recursively */
    result = malloc (size);
    /* Save underlying hooks */
    old_malloc_hook = __malloc_hook;
    old_free_hook = __free_hook;
    /* printf might call malloc, so protect it too. */
    printf ("malloc (%u) returns %p\n", (unsigned int) size, result);
    /* Restore our own hooks */
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
    return result;
}
    
     static void
          my_free_hook (void *ptr, const void *caller)
{
    /* Restore all old hooks */
    __malloc_hook = old_malloc_hook;
    __free_hook = old_free_hook;
    /* Call recursively */
    free (ptr);
    /* Save underlying hooks */
    old_malloc_hook = __malloc_hook;
    old_free_hook = __free_hook;
    /* printf might call free, so protect it too. */
    printf ("freed pointer %p\n", ptr);
    /* Restore our own hooks */
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
}
    
int    main ()
     {
         char *a=(char *)malloc(20);                         
         free(a);

   }

# ./handle

malloc (20) returns 0x804a008
freed pointer 0x804a008
4 使用backtrace 获取堆栈信息
gcc提供很方便的函数来干这活,windows就太麻烦了。
#include <execinfo.h>
static void test2()
{
int i = 0;
void* buffer[MAX_LEVEL] = {0};

int size = backtrace(buffer, MAX_LEVEL);

for(i = 0; i < size; i++)
{
  printf("called by %p\n", buffer[i]);
}

return;
}
跑完之后大家不知道有什么想法没
5 使用memory hook + backtrace获取C++ 对象创建信息
这个是重点:)
据我推测,没有去check gcc malloc() code确认,其实mhook就是把调用的地址传给hook函数而已,那么c++的new 其实可以跟踪出来的,就在mhook里加上backtrace就行
代码就不贴了,把上面的组合一下就可以。已经实验确认过, 想知道c++是否内存泄露可以用这个来check,如果不想用其他大型工具的话。

注意编译时要打开debug信息,否则得不到具体地址。如果是非debug版可以使用编译生成的map文件进行大致定位。
由memory hook推广开来,如果在其他资源比如pthread的一些操作里增加backtrace的check我们可以获取详细的线程,锁信息,获取这个干嘛就不用说了吧。可惜pthread没有hook,只能自己做wraper了。

一个想法,既然gcc已经提供了这么丰富的工具,其实我们可以把这些信息存下来或者发送出去,可以得知程序的详细信息,然后用工具分析 就像java profiler那样,检查资源分配的粒度频度,是否死锁等等


0
1
分享到:
评论

相关推荐

    gcc C语言API

    GCC C语言API中的函数和类在设计时考虑到了异常中立性,即这些组件可以在存在异常的情况下正常工作,不会因为异常而影响到程序的整体稳定性。 #### 七、GCC C语言API的调试支持 ##### 7.1 使用g++编译器 GCC ...

    C语言程序设计-图书管理系统

    《C语言程序设计-图书管理系统》是一个典型的C语言编程项目,旨在帮助用户管理和查询图书信息。这个系统在大学二年级时由作者和他的团队成员共同完成,对于初学者来说,它是一个很好的实践案例,有助于深入理解和...

    C/C++程序内存泄漏检测

    在C/C++编程中,内存管理是至关重要的,因为这些语言不提供自动的垃圾回收机制。程序员必须手动分配和释放内存,如果不小心就会导致内存泄漏,即已经分配但未释放的内存。内存泄漏可能导致程序运行缓慢,占用过多...

    C语言经典《C程序设计语言》(电子版)

    10. **编译与链接**:书中也涵盖了C程序的编译和链接过程,解释了如何使用编译器(如gcc)将源代码转换为可执行文件。 总的来说,《C程序设计语言》是一本全面且深入的教程,不仅适合初学者,也是经验丰富的程序员...

    gcc编译器完全介绍中文版

    在Linux系统中,可以使用包管理器如apt或yum来安装预编译的版本,或者从GCC官网获取源码进行编译安装。配置时,用户可以指定安装路径、选择要编译的语言和支持的特性。 三、GCC的使用 使用GCC编译源代码,通常通过...

    gcc-11.3.0及其依赖包

    6. **调试信息**:GCC 11.3.0可能改进了调试信息的生成,使得开发者使用GDB等调试工具时能够获得更准确、更详尽的信息,帮助定位和解决问题。 7. **代码分析工具**:GCC还包含了静态代码分析工具,如`-Wall`和`-...

    gcc+dev c++

    标题中的“gcc+dev c++”指的是在Windows环境下进行C语言开发时常用的两个工具:GCC(GNU Compiler Collection)和Dev-C++。GCC是一款开源的编译器,支持多种编程语言,包括C、C++等,而Dev-C++则是一款集成开发环境...

    gcc详细使用说明(很棒的)

    例如,在C语言方面,GCC支持C89/C90、C99以及C11等标准。对于C++,GCC支持C++98、C++03、C++11、C++14等多个版本的标准。这使得GCC成为了一个非常灵活的工具,可以根据项目的具体需求选择合适的语言标准进行编译。 ...

    c语言程序设计《商店商品管理系统》

    在C语言中,程序设计通常涉及以下几个关键知识点: 1. **基础语法**:C语言的程序设计始于基本语法,包括变量定义、数据类型(如int, char, float等)、运算符(如算术运算符、关系运算符、逻辑运算符等)以及流程...

    gcc编译工具(C语言)

    在Windows环境下,通常会使用MinGW64这样的工具链来获取GCC编译器,以便在Windows系统上编译和运行C语言程序。** **GCC的工作流程主要包括预处理、编译、汇编和链接四个阶段:** 1. **预处理(Preprocessing)**:...

    complier-gcc5

    在这个案例中,用户可能需要解压这个文件以获取GCC 5的安装程序、库文件或者开发工具。 标签"compliergcc5"是对主题的简短概括,再次强调了这是关于GCC的5版本内容。 压缩文件内的"compiler-gcc5.h"可能是头文件,...

    GCC manual

    ### GCC (GNU Compiler Collection) 手册...综上所述,GCC作为一款强大的开源编译器集合,在C/C++等语言的开发中扮演着极其重要的角色。通过深入了解GCC的各项功能和技术细节,开发者能够更高效地进行软件开发工作。

    tdm64-gcc-10.3.0-2.exe

    通过TDM-GCC,Windows用户能够轻松获得一套强大的开源编译工具链,这对于学习和开发C和C++程序尤其方便。同时,对于那些习惯于Linux环境但在Windows上工作的开发者来说,TDM-GCC提供了一个熟悉的工作环境。

    avr的gcc编程(初学者必看)

    - **混合编程技巧**: 在C程序中嵌入汇编代码片段,或在汇编程序中调用C函数。 - **注意事项**: 确保数据类型匹配和栈一致性。 #### 十、C++语言支持 - **C++支持**: AVR-GCC支持C++编程,允许开发者利用面向对象...

Global site tag (gtag.js) - Google Analytics