Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在调用malloc/free时输出到stderr_C++_Linux_Memory_Malloc_Valgrind - Fatal编程技术网

C++ 在调用malloc/free时输出到stderr

C++ 在调用malloc/free时输出到stderr,c++,linux,memory,malloc,valgrind,C++,Linux,Memory,Malloc,Valgrind,在Linux/GCC/C++中,每当调用malloc/free/new/delete时,我都想向stderr记录一些东西。我试图理解库的内存分配,所以我想在运行单元测试时生成这个输出。我使用valgrind进行mem泄漏检测,但我找不到一个选项使其仅用于日志分配 有什么想法吗?我在寻找最简单的解决办法。重新编译库不是一个选项 < P>(向下滚动)提供了一个非常清楚和简洁的描述,说明如何在C++中重写全局代码< >新< /C> >和删除>代码>(注意它没有提供一个例子,用于 NeX[]/COD>,

在Linux/GCC/C++中,每当调用malloc/free/new/delete时,我都想向stderr记录一些东西。我试图理解库的内存分配,所以我想在运行单元测试时生成这个输出。我使用valgrind进行mem泄漏检测,但我找不到一个选项使其仅用于日志分配

有什么想法吗?我在寻找最简单的解决办法。重新编译库不是一个选项

< P>(向下滚动)提供了一个非常清楚和简洁的描述,说明如何在C++中重写全局代码< >新< /C> >和<代码>删除>代码>(注意它没有提供一个例子,用于<代码> NeX[]/COD>,但是它在概念上是类似的。
至于覆盖malloc和free,因为您使用的是Linux和GCC,最简单的方法是使用
malloc\u hook
free\u hook
。这是对这些函数如何工作的一个很好的描述。

我自己没有测试过,但我非常确定这些函数会工作:

  • 因为您不想重新编译库,所以提供有意义的输出(而只是“newcalledfor23字节”)可能需要获取堆栈跟踪。我记得使用函数来导航堆栈,但我现在找不到它们。也许对system()和pstack(1)的调用就可以做到这一点

  • >p>可以重新定义运算符new和DELL,并将这个新定义放在STD C++库前面。这可能无法捕获来自相关库正在使用的容器和标准组件的调用。这需要重新链接

  • Use可以使用LD_PRELOAD动态更改运算符new和delete。如果应用程序是动态链接的,则不需要重新链接


希望这些指针能有所帮助,很抱歉我没有配方。

您可以使用ltrace跟踪malloc/free的呼叫:

#include <stdlib.h>

int main (void)
{
  void *ptr = malloc(10);
  free(ptr);

  return 0;
}


$ g++ test.cpp -o test
$ ltrace -e malloc,free ./test
malloc(10)                                       = 0x804a008
free(0x804a008)                                  = <void>
+++ exited (status 0) +++
#包括
内部主(空)
{
void*ptr=malloc(10);
免费(ptr);
返回0;
}
$g++test.cpp-o测试
$ltrace-e malloc,免费。/test
malloc(10)=0x804a008
免费(0x804a008)=
+++已退出(状态0)+++
要在不重新编译的情况下跟踪新的/删除调用,您可能需要使用类似LD_PRELOAD的东西来用您自己的版本覆盖调用,这正是您想要做的。

允许您全局插入您自己的
malloc
函数。(还有
\uuuu realloc\uhook
\uuu free\uhook
等。为了简单起见,我刚刚省略了它们。)

#包括
#包括
静态空隙*(*旧马洛克钩)(尺寸,常数空隙*);
静态void*新的malloc\u钩子(大小、常量void*调用者){
void*mem;
__malloc_hook=旧的malloc_hook;
mem=malloc(尺寸);
fprintf(stderr,“%p:malloc(%zu)=%p\n”,调用者,大小,内存);
__malloc_hook=新的malloc_hook;
返回mem;
}
静态void init_my_挂钩(void){
old_malloc_hook=_malloc_hook;
__malloc_hook=新的malloc_hook;
}
void(*malloc_initialize_hook)(void)=init_my_hook;

$cat>mem.c这两种解决方案似乎都需要重新编译所讨论的库。
#include <stdio.h>
#include <malloc.h>

static void *(*old_malloc_hook)(size_t, const void *);

static void *new_malloc_hook(size_t size, const void *caller) {
    void *mem;

    __malloc_hook = old_malloc_hook;
    mem = malloc(size);
    fprintf(stderr, "%p: malloc(%zu) = %p\n", caller, size, mem);
    __malloc_hook = new_malloc_hook;

    return mem;
}

static void init_my_hooks(void) {
    old_malloc_hook = __malloc_hook;
    __malloc_hook = new_malloc_hook;
}

void (*__malloc_initialize_hook)(void) = init_my_hooks;
$ cat >mem.c <<'EOF' (the code above) EOF $ cc -fPIC -shared -o mem.so mem.c $ LD_PRELOAD=./mem.so ls 0x7ffc14931adc: malloc(5) = 0xb40010 0x7ffc1492c6b0: malloc(120) = 0xb40030 0x7ffc1497f61a: malloc(12) = 0xb40010 0x7ffc1492be38: malloc(776) = 0xb400b0 …