免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 849 | 回复: 0
打印 上一主题 下一主题

Alloc Debugging [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-03-20 10:57 |只看该作者 |倒序浏览
How to install the tracing functionality
— Function: void mtrace (void)
When the mtrace function is called it looks for an environment variable named MALLOC_TRACE. This variable is supposed to contain a valid file name. The user must have write access. If the file already exists it is truncated. If the environment variable is not set or it does not name a valid file which can be opened for writing nothing is done. The behavior of malloc etc. is not changed. For obvious reasons this also happens if the application is installed with the SUID or SGID bit set.
If the named file is successfully opened, mtrace installs special handlers for the functions malloc, realloc, and free (see Hooks for Malloc). From then on, all uses of these functions are traced and protocolled into the file. There is now of course a speed penalty for all calls to the traced functions so tracing should not be enabled during normal use.
This function is a GNU extension and generally not available on other systems. The prototype can be found in mcheck.h.
— Function: void muntrace (void)
The muntrace function can be called after mtrace was used to enable tracing the malloc calls. If no (successful) call of mtrace was made muntrace does nothing.
Otherwise it deinstalls the handlers for malloc, realloc, and free and then closes the protocol file. No calls are protocolled anymore and the program runs again at full speed.
This function is a GNU extension and generally not available on other systems. The prototype can be found in mcheck.h.

.2.3.2 Example program excerpts
Even though the tracing functionality does not influence the runtime behavior of the program it is not a good idea to call mtrace in all programs. Just imagine that you debug a program using mtrace and all other programs used in the debugging session also trace their malloc calls. The output file would be the same for all programs and thus is unusable. Therefore one should call mtrace only if compiled for debugging. A program could therefore start like this:      #include
     
     int
     main (int argc, char *argv[])
     {
     #ifdef DEBUGGING
       mtrace ();
     #endif
       ...
     }
This is all what is needed if you want to trace the calls during the whole runtime of the program. Alternatively you can stop the tracing at any time with a call to muntrace. It is even possible to restart the tracing again with a new call to mtrace. But this can cause unreliable results since there may be calls of the functions which are not called. Please note that not only the application uses the traced functions, also libraries (including the C library itself) use these functions.
This last point is also why it is no good idea to call muntrace before the program terminated. The libraries are informed about the termination of the program only after the program returns from main or calls exit and so cannot free the memory they use before this time.
So the best thing one can do is to call mtrace as the very first function in the program and never call muntrace. So the program traces almost all uses of the malloc functions (except those calls which are executed by constructors of the program or used libraries).

Memory Allocation Hooks
The GNU C library lets you modify the behavior of malloc, realloc, and free by specifying appropriate hook functions. You can use these hooks to help you debug programs that use dynamic memory allocation, for example.
The hook variables are declared in malloc.h.
— Variable: __malloc_hook
The value of this variable is a pointer to the function that malloc uses whenever it is called. You should define this function to look like malloc; that is, like:
          void *function (size_t size, const void *caller)
     
The value of caller is the return address found on the stack when the malloc function was called. This value allows you to trace the memory consumption of the program.
— Variable: __realloc_hook
The value of this variable is a pointer to function that realloc uses whenever it is called. You should define this function to look like realloc; that is, like:
          void *function (void *ptr, size_t size, const void *caller)
     
The value of caller is the return address found on the stack when the realloc function was called. This value allows you to trace the memory consumption of the program.
— Variable: __free_hook
The value of this variable is a pointer to function that free uses whenever it is called. You should define this function to look like free; that is, like:
          void function (void *ptr, const void *caller)
     
The value of caller is the return address found on the stack when the free function was called. This value allows you to trace the memory consumption of the program.
— Variable: __memalign_hook
The value of this variable is a pointer to function that memalign uses whenever it is called. You should define this function to look like memalign; that is, like:
          void *function (size_t size, size_t alignment, const void *caller)
     
The value of caller is the return address found on the stack when the memalign function was called. This value allows you to trace the memory consumption of the program.
You must make sure that the function you install as a hook for one of these functions does not call that function recursively without restoring the old value of the hook first! Otherwise, your program will get stuck in an infinite recursion. Before calling the function recursively, one should make sure to restore all the hooks to their previous value. When coming back from the recursive call, all the hooks should be resaved since a hook might modify itself.
— Variable: __malloc_initialize_hook
The value of this variable is a pointer to a function that is called once when the malloc implementation is initialized. This is a weak variable, so it can be overridden in the application with a definition like the following:
          void (*__malloc_initialize_hook) (void) = my_init_hook;
     
An issue to look out for is the time at which the malloc hook functions can be safely installed. If the hook functions call the malloc-related functions recursively, it is necessary that malloc has already properly initialized itself at the time when __malloc_hook etc. is assigned to. On the other hand, if the hook functions provide a complete malloc implementation of their own, it is vital that the hooks are assigned to before the very first malloc call has completed, because otherwise a chunk obtained from the ordinary, un-hooked malloc may later be handed to __free_hook, for example.
In both cases, the problem can be solved by setting up the hooks from within a user-defined function pointed to by __malloc_initialize_hook—then the hooks will be set up safely at the right time.
Here is an example showing how to use __malloc_hook and __free_hook properly. It installs a function that prints out information every time malloc or free is called. We just assume here that realloc and memalign are not used in our program.
     /* Prototypes for __malloc_hook, __free_hook */
     #include
     
     /* 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 *);
     
     /* 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;
     }
     
     main ()
     {
       ...
     }



本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/30686/showart_261748.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP