对于c++ arm应用程序,我需要跟踪内存分配。对此,我是用gcc的记忆钩。现在,我正在打印分配和释放,请参阅下面的代码。
然而,malloc和free没有加起来。有时我在内存块上看到一个free,它以前没有malloc挂钩,或者内存被释放了两次。当然,这在我的代码中可能是一个错误,尽管我没有得到分段错误。但我也看到,malloc有时会返回它以前返回的指针,同时也没有free (至少我的空闲钩子没有被调用)。
因此,我的猜测是,某些malloc和free'不是通过我的钩子传递的。请注意,当我只跟踪c++分配时,情况就会变得很好。
有人有什么想法吗?
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <new>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
pthread_mutex_t lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static void push_memhooks();
static void pop_memhooks();
static void *malloc_hook(size_t size, const void *ret)
{
pthread_mutex_lock(&lock);
pop_memhooks();
void *mem = malloc(size);
if (mem) {
printf("malloc %p\n", mem);
}
push_memhooks();
pthread_mutex_unlock(&lock);
return mem;
}
static void *realloc_hook(void* ptr, size_t size, const void *ret)
{
pthread_mutex_lock(&lock);
pop_memhooks();
void* mem = realloc(ptr, size);
if (mem) {
printf("realloc %p -> %p\n", ptr, mem);
}
push_memhooks();
pthread_mutex_unlock(&lock);
return mem;
}
static void* memalign_hook(size_t boundary, size_t size, const void *ret)
{
pthread_mutex_lock(&lock);
pop_memhooks();
void* mem = memalign(boundary, size);
if (mem) {
printf("memalign %p\n", mem);
}
push_memhooks();
pthread_mutex_unlock(&lock);
return mem;
}
static void free_hook(void *mem, const void *ret)
{
pthread_mutex_lock(&lock);
pop_memhooks();
free(mem);
printf("free %p\n", mem);
push_memhooks();
pthread_mutex_unlock(&lock);
}
void *operator new(size_t size)
{
void* mem = malloc(size);
if (!mem) {
throw std::bad_alloc();
}
return mem;
}
void operator delete(void* mem)
{
free(mem);
}
void *operator new[](size_t size)
{
void* mem = malloc(size);
if (!mem) {
throw std::bad_alloc();
}
return mem;
}
void operator delete[](void* mem)
{
free(mem);
}
static int memhooks = 0;
static void push_memhooks()
{
if (++memhooks == 1) {
__malloc_hook = malloc_hook;
__realloc_hook = realloc_hook;
__free_hook = free_hook;
__memalign_hook = memalign_hook;
}
}
static void pop_memhooks()
{
if (--memhooks == 0) {
__malloc_hook = NULL;
__realloc_hook = NULL;
__free_hook = NULL;
__memalign_hook = NULL;
}
}
static void install_memhooks ()
{
push_memhooks();
}
void (*__malloc_initialize_hook)(void) = install_memhooks;例如,当我对显示奇怪行为的指针的跟踪进行grep时,会得到以下输出。
<snip>
malloc 0x8234818
free 0x8234818
malloc 0x8234818
malloc 0x8234818
free 0x8234818
<snip>注意两个连续的malloc。
解决方案:正如克里斯在他的答案中提到的,上面的代码中有一个竞争条件。不幸的是,在以我的方式删除和重新安装钩子时,malloc钩子不能安全地在多线程环境中使用。出于同样的原因,mcheck不能在多线程应用程序(http://sources.redhat.com/bugzilla/show_bug.cgi?id=9939)中使用。
实现malloc/realloc/free和使用dlsym(RTLD_NEXT, "malloc")调用libc版本也不起作用。首先,dlsym调用calloc,因此需要特别小心来防止这里的无限递归。其次,当调用libc malloc时,进程挂起。此外,我看到我的__malloc_initialize_hook没有被调用。所以我想,通过提供我自己的malloc实现,libc malloc没有被正确初始化。
我的当前解决方案嵌入了dlmalloc实现,以消除对libc的依赖。现在,我不必继续删除/重新安装malloc钩子。我只安装了一次钩子,我的钩子使用dlmalloc分配内存。
发布于 2010-11-15 18:23:52
如果您是在多线程环境中运行的,那么您的竞争条件可能会导致您错过对malloc/free的调用。当您的malloc_hook函数被调用时,它会解开所有钩子,调用malloc,然后重新挂钩这些钩子。如果在解钩时其他线程调用malloc/free,则不会看到该调用。您的互斥没有帮助,就像拔下钩时,malloc/free调用不会调用钩子函数,因此不会等待互斥。
编辑
在程序中连接/监视malloc的首选方法是使用宏来拦截程序中的调用,而不必担心stdlib中的调用。使用以下内容创建一个wrap_malloc文件:
#define malloc(sz) wrap_malloc(sz, __FILE__, __LINE__)
#define free(p) wrap_free(p, __FILE__, __LINE__)
#define realloc(p, sz) wrap_realloc(p, sz, __FILE__, __LINE__)
#define calloc(s1, s2) wrap_calloc(s1, s2, __FILE__, __LINE__)然后用-imacros wrap_malloc编译我的所有代码。定义wrap_malloc和朋友的文件只需要适当的#undef,但不需要对代码进行其他更改。
发布于 2010-11-15 15:18:41
我不知道您控制这段代码的扩展,以及您如何尝试检测malloc/free是否匹配。但有一件事可能会发生,那就是他们中的任何一个都伪装成了realloc。这种类型的参数可以与malloc (初始指针为0)或free (新大小为0)具有相同的效果。
编辑:,我看到你在使用线程吗?另一种可能是您的malloc/free按顺序进行,但是用于调试输出的printf出现了故障。对FILE*变量的访问通常是互斥的。尝试在调试输出前加上时间戳,并根据时间戳进行第一次排序。
https://stackoverflow.com/questions/4184280
复制相似问题