首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >gcc的记忆钩子有时会被绕过吗?

gcc的记忆钩子有时会被绕过吗?
EN

Stack Overflow用户
提问于 2010-11-15 12:25:33
回答 2查看 1.8K关注 0票数 1

对于c++ arm应用程序,我需要跟踪内存分配。对此,我是用gcc的记忆钩。现在,我正在打印分配和释放,请参阅下面的代码。

然而,mallocfree没有加起来。有时我在内存块上看到一个free,它以前没有malloc挂钩,或者内存被释放了两次。当然,这在我的代码中可能是一个错误,尽管我没有得到分段错误。但我也看到,malloc有时会返回它以前返回的指针,同时也没有free (至少我的空闲钩子没有被调用)。

因此,我的猜测是,某些mallocfree'不是通过我的钩子传递的。请注意,当我只跟踪c++分配时,情况就会变得很好。

有人有什么想法吗?

代码语言:javascript
运行
复制
#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时,会得到以下输出。

代码语言:javascript
运行
复制
<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分配内存。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-11-15 18:23:52

如果您是在多线程环境中运行的,那么您的竞争条件可能会导致您错过对malloc/free的调用。当您的malloc_hook函数被调用时,它会解开所有钩子,调用malloc,然后重新挂钩这些钩子。如果在解钩时其他线程调用malloc/free,则不会看到该调用。您的互斥没有帮助,就像拔下钩时,malloc/free调用不会调用钩子函数,因此不会等待互斥。

编辑

在程序中连接/监视malloc的首选方法是使用宏来拦截程序中的调用,而不必担心stdlib中的调用。使用以下内容创建一个wrap_malloc文件:

代码语言:javascript
运行
复制
#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,但不需要对代码进行其他更改。

票数 1
EN

Stack Overflow用户

发布于 2010-11-15 15:18:41

我不知道您控制这段代码的扩展,以及您如何尝试检测malloc/free是否匹配。但有一件事可能会发生,那就是他们中的任何一个都伪装成了realloc。这种类型的参数可以与malloc (初始指针为0)或free (新大小为0)具有相同的效果。

编辑:,我看到你在使用线程吗?另一种可能是您的malloc/free按顺序进行,但是用于调试输出的printf出现了故障。对FILE*变量的访问通常是互斥的。尝试在调试输出前加上时间戳,并根据时间戳进行第一次排序。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4184280

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档