linux c中的fopen():分段故障

6l7fqoea  于 2022-11-22  发布在  Linux
关注(0)|答案(1)|浏览(249)

我尝试 Package C库函数mallocfree,以检测代码中是否存在内存泄漏。我扩展了malloc/free函数,向它们添加了一个fprintf,以将malloc/free的地址和大小写入文件。
使用gcc或clang**编译此代码会在fopen()行中产生分段错误。**以下是命令:
gcc -o mainapp main.c -Wall -Wextra
我将fopen放在malloc和free函数中,但也会遇到同样的问题:分段错误(核心转储)
我找不到这个问题的解释。
下面是我的完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define __USE_GNU
#include <dlfcn.h>

#define TEST_MEM_LEAK 1 // a value of 1 means to join the memory leak detection, and a value of 0 means not to join

#if TEST_MEM_LEAK

typedef void *(*malloc_t)(size_t size);
malloc_t malloc_f = NULL;

typedef void (*free_t)(void *p);
free_t free_f = NULL;

int malloc_flag = 1;    // It is used to prevent repeated recursion and cannot exit because the printf function will call malloc for memory allocation
int free_flag = 1;
const char* logFileName = "/home/hammamiw/Documents/HeapMonitor/allocs.log";
FILE* fp = NULL;

void initCheck()
{
    fp = fopen("/home/hammamiw/Documents/HeapMonitor/allocs.log", "w");
}

void *malloc(size_t size)
{
    if(malloc_flag) { 
        initCheck();  
        malloc_flag = 0;  // Used to prevent printf from causing an error when calling malloc recursively
        void *p = malloc_f(size);
        fprintf(fp, "malloc, %lx, %lu\n", (uintptr_t)p, size);
        //printf("m\n");
        malloc_flag = 1;  // It is used to ensure that the initial value of flag flag is consistent when malloc in this file is called again
        return p;
    } 
    else {
        return malloc_f(size);  // Here, the malloc function in the system library obtained by dlsym is called
    }   
}

void free(void *p) 
{
    initCheck();
    if(free_flag) {
        //initCheck();  
        free_flag = 0;
        fprintf(fp, "F, %lx\n", (uintptr_t)p);
        //printf("f\n");
        free_f(p);
       free_flag = 1;
    } else {
        free_f(p);
    }
}
#endif

int main()
{
#if TEST_MEM_LEAK // the part from if to endif can be divided into function calls
    malloc_f = dlsym(RTLD_NEXT, "malloc");
    if(!malloc_f) {
        printf("load malloc failed: %s\n", dlerror());
        return 1;
    }
    free_f = dlsym(RTLD_NEXT, "free");
    if(!free_f) {
        printf("load free failed: %s\n", dlerror());
        return 1;
    }
#endif
    void *p1 = malloc(10);  //The malloc function in this article will be called first
    void *p2 = malloc(20);
    
    //Here, p2 is not released and there is a memory leak. Judge by checking whether the number of malloc and free times printed is the same
    free(p2);
    free(p1);
    return 0;
}

注意:如果我使用printf而不是fprintf -〉在每次free和malloc调用时打印“f”和“m”,代码运行得很好。
使用环境:Ubuntu 22.04,C语言,GCC编译器版本11.3.0

x6yk4ghg

x6yk4ghg1#

您需要在调用fopen()之前设置malloc_flag,这样您不仅可以防止通过fprintf()的递归,还可以防止通过fopen()的递归。

相关问题