首页 > 解决方案 > 如何在同一个包装函数中使用使用 malloc 的函数预加载共享库和包装 malloc?

问题描述

我想包装malloc一个函数来打印分配大小、指针地址和分配时间。这可以通过我的实现预加载我的共享库来实现malloc。这段代码实现了:

#define _GNU_SOURCE

#include <stdio.h>
#include <dlfcn.h>

static void* (*real_malloc)(size_t size) = NULL;
static void* (*real_calloc)(size_t nelements, size_t elementSize) = NULL;

static void init(void)
{
    real_malloc = dlsym(RTLD_NEXT, "malloc");
    if (NULL == real_malloc)
    {
        fprintf(stderr, "Error: %s\n", dlerror());
    }
}

void *malloc(size_t size)
{
    if(real_malloc == NULL)
    {
        init();
    }

    void *p = NULL;

    p = real_malloc(size);
    fprintf(stderr, "size=%lu, pointer=%p\n", size, p);
    return p;
}

但是,如果我将时间打印功能添加到malloc

static void printTime()
{
  time_t timer;
    char buffer[26];
    struct tm* tm_info;

    time(&timer);
    tm_info = localtime(&timer);

    strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
    fprintf(stderr, "%s\n", buffer);
}

并添加time.h标题并使用可执行文件运行我的 .so 库,它只会冻结并且什么都不做。

我怀疑time或者在引擎盖下localtime打电话,这会导致问题。malloc另一方面real_malloc,确实被调用了,所以应该没有问题。

我的可执行文件是多线程的,但添加互斥锁并没有帮助。我编译.so的方式如下:

gcc -fPIC -shared -o bin/libpreload.so myAlloc.c -ldl

该问题可以使用 Linuxps程序进行验证:

cd /bin && LD_PRELOAD=/home/username/Desktop/alloc/bin/libpreload.so ./ps

下面也是ldd我的.so的输出: 在此处输入图像描述

标签: clinkermockingmallocshared-libraries

解决方案


如果您的日志记录函数malloc最终调用malloc,您需要跳出递归循环。

因此,只有在您的日志记录之外调用 malloc 时才进行日志记录。

void *malloc(size_t size)
{
    if(real_malloc == NULL)
    {
        init();
    }

    void *p = NULL;

    p = real_malloc(size);

    if (do_logging)
      {
         do_logging = 0;
         fprintf(stderr, "size=%lu, pointer=%p\n", size, p);
         printTime();
         do_logging = 1;
      }
    return p;
}

自然,如果您希望它在多线程程序中工作,您必须放入do_logging线程本地存储。在 c11 及更高版本中,您可以这样做:

#include <threads.h>
thread_local int do_logging = 1;

哦,你的init-function 可能不是线程安全的。


推荐阅读