c - 如何在同一个包装函数中使用使用 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
解决方案
如果您的日志记录函数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 可能不是线程安全的。
推荐阅读
- html - 如何使用内联块
- php - sql中没有插入数据
- c# - 如何有效地将 HTTP GET 的数据通过管道传输到 .NET 中的 HTTP PUT?
- php - 我通过 php 标头强制下载的速度太慢,无法用于商业用途
- excel - 如何将列表参数传递给 Excel 中的 ODBC 查询(Microsoft Query)
- r - 如何使选定的表仅限于矩阵而不是运行列表?
- android - Android:根据用户设置以编程方式更改 SourceSet
- excel - VBA - 从所有模块受密码保护的工作簿中运行宏
- javascript - Cypress.io:如何创建有助于根据输入选择不同 DOM 元素的函数
- html - 如何让我的表单从页面顶部开始?每当单击“下一步”按钮时,都会一直滚动到底部