【问题标题】:overriding malloc, free and calloc cause recursion in Linux在 Linux 中覆盖 malloc、free 和 calloc 导致递归
【发布时间】:2018-05-01 04:41:28
【问题描述】:

我在Linux平台上重写了malloccallocfree函数如下:

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
typedef void* (*MALLOCFN)(size_t);
typedef void* (*CALLOCFN)(size_t, size_t);
typedef void* (*CALLOCFN)(size_t, size_t);
typedef void (*FREEFN)(void *);
MALLOCFN real_malloc = (MALLOCFN) 0;
CALLOCFN real_calloc = (CALLOCFN) 0;
FREEFN real_free = (FREEFN) 0;
void *get_realfn(const char *fnm)
{
  void *pfunc = (void *) NULL;
  printf("searching for original %s\n", fnm);
  pfunc = dlsym(RTLD_NEXT, fnm);
  if (pfunc) printf("found original %s\n", fnm);
  else printf("not found original %s\n", fnm);
  return pfunc;
}
void *malloc(size_t s)
{
  printf("called malloc\n");
  if(real_malloc == NULL) real_malloc = (MALLOCFN) get_realfn("malloc");
  if (real_malloc) return real_malloc(s);
  else return NULL;
}
void *calloc(size_t s1, size_t s2)
{
  printf("called calloc\n");
  if(real_calloc == NULL) real_calloc = (CALLOCFN) get_realfn("calloc");
  if (real_calloc) return real_calloc(s1, s2);
  else return NULL;
}
void free (void * ptr)
{
  printf("called free\n");
  if(real_free == NULL) real_free = (FREEFN) get_realfn("free");
  if (real_free) real_free(ptr);
}
int main()
{
  char * c1 = (char *) malloc(400);
  char * c2 = (char *) malloc(400);
  free(c2); free(c1);
  return 0;
}

C程序(testalloc.c)是使用g++ 4.9.2版本编译器构建的:

g++ -g testalloc.c  -ldl -o testalloc;

前几行输出如下,进入无限递归崩溃:

called malloc
searching for original malloc
called free
searching for original free
called free
searching for original free
called free
searching for original free
called free
searching for original free
called free
. . . .

请建议如何避免递归。

【问题讨论】:

  • gcc,换行选项。

标签: c linux recursion memory-management malloc


【解决方案1】:

printf 函数可以分配内存。因此,当您调用 printfbefore 时,未分配“真实”函数指针,它会进入您的插入函数,导致无限递归。所以不要在插入函数中使用printf 语句。

如果您确实需要打印某些内容,请使用 syscall(2),它会绕过 stdio 库函数。

#include <sys/syscall.h>

...

syscall(SYS_write, STDOUT_FILENO, "searching for original\n",
                                  sizeof "searching for original\n" - 1);

【讨论】:

  • 为什么要打扰syscall( SYS_write...)?只需使用write()
  • 可能。我想是习惯。
  • 这样更好,dlsym会导致调用malloc或calloc吗?我的调试器显示从 malloc 到最终 dlsym 的调用,然后到 calloc 导致无限递归,我可以避免从 dlsym 调用覆盖的 malloc/calloc 吗?
  • dlsym 不分配,除非它失败(当前 glibc 实现)。所以是的,这是可能的。如果你想让它安全,你可能需要为 dlsym 提供一个单独的分配器。查看一些现有的库(例如 TCmalloc、Jemalloc 等)了解它是如何完成的。
  • dlsym 似乎失败了,我怎样才能让 dlsym 不陷入这个麻烦?
猜你喜欢
  • 2010-10-30
  • 1970-01-01
  • 1970-01-01
  • 2019-11-15
  • 2012-07-20
  • 2011-05-05
  • 1970-01-01
  • 2019-02-24
  • 2012-03-02
相关资源
最近更新 更多