在自己的malloc函数中调用printf导致分段错误

在自己的malloc函数中调用printf导致分段错误,c,memory,segmentation-fault,printf,malloc,C,Memory,Segmentation Fault,Printf,Malloc,我想用Linux GCC在纯C中“重写”malloc,用于内存检查。请注意,malloc()是一个弱符号,在纯C中这样做是可以的。例如,制作一个malloc()的强符号 但我刚刚发现,如果在我的malloc()实现中调用printf(),它会崩溃,如果删除,它不会崩溃 复制: #include <stdio.h> extern void *__libc_malloc(size_t size); static int cnt = 0; void* malloc(size_t si

我想用Linux GCC在纯C中“重写”
malloc
,用于内存检查。请注意,
malloc()
是一个弱符号,在纯C中这样做是可以的。例如,制作一个
malloc()
的强符号

但我刚刚发现,如果在我的
malloc()
实现中调用
printf()
,它会崩溃,如果删除,它不会崩溃

复制:

#include <stdio.h>

extern void *__libc_malloc(size_t size);

static int cnt = 0;

void* malloc(size_t size) {
    printf("--- calling customized malloc\n");
    cnt += 1;
    if(cnt > 1) return NULL;

    return __libc_malloc(size);
}

static void leak_test1() {
    int* a = malloc(sizeof(int)*5);
    a[0] = 3;
}

int main(){
    leak_test1();
    printf("cnt=%d\n", cnt);

    return 0;
}
#包括
外部无效*uuu libc_umalloc(大小);
静态int cnt=0;
void*malloc(大小){
printf(“---调用自定义malloc\n”);
cnt+=1;
如果(cnt>1)返回NULL;
返回uu libc_malloc(大小);
}
静态空隙泄漏试验1(){
int*a=malloc(sizeof(int)*5);
a[0]=3;
}
int main(){
泄漏测试1();
printf(“cnt=%d\n”,cnt);
返回0;
}

这是否意味着“在我自己的malloc()中调用printf无效”?深层次原因是什么?(如果我错了,请纠正我)

有可能
printf
调用
malloc
stdout
分配缓冲区,因此您会得到无限递归


您可以通过调用
fprintf(stderr,…)
来绕过这个问题,因为
stderr
是无缓冲的。

我怀疑
printf
调用
malloc
来分配其缓冲区,在这种情况下,您会创建一个无限递归。您可能需要为输出绕过stdio,或者在
malloc
返回后将其排队并打印出来。如果
printf
调用
malloc
,则创建了一个递归循环并炸毁了堆栈。@TomKarzes是的,我还认为printf调用malloc,从而递归调用…我将变量
cnt
,但是我应该在调用
printf
之前检查
cnt
。尝试用
put
替换
printf
-cnt应该做什么?向上计数直到引发整数溢出?这是一个bug。printf怎么知道被叫方翻译单元中的malloc呢?为了使用malloc,它必须从“stdio.c”标准库中包含stdlib.h,在这种情况下,malloc是正确的,而不是“重载”的。您所描述的行为应该只有在printf的整个函数都是类似于宏的情况下才可能发生,我对此表示怀疑。我宁愿怀疑这一点:库中的malloc函数定义不是命名为
malloc
,而是其他名称。然后在stdlib.h中,它们有一些技巧,既有正确的
malloc
函数声明,也有一些宏通过调用内部“something\u else\u malloc”(允许标准库这样做)来重载函数声明。但是,当调用方实际提供名为
malloc
的函数定义时,该函数定义被链接,宏技巧中断。在那之后,您描述的无限递归是可能的。否则,如果stdlib malloc也被命名为
malloc
,那么程序甚至不应该链接。@Lundin:您所描述的是可能的,但我怀疑
malloc
不是一个带有
中某些属性的简单外部声明。弱符号和动态符号解析的精确语义对我来说有些模糊,甚至在linux环境中,对大多数程序员来说也可能是陌生的。我建议使用一个简单的测试来检查缓冲是否是问题所在(不是一个正式的证明,而是一个强有力的指示)。OP没有对这个建议发表评论,但接受了答案,所以我的建议一定解决了问题。