按照人的建议释放内存会在 valgrind 中产生错误

Freeing memory as man suggests yields errors in valgrind

我正在尝试释放像这样初始化的结构

MemFile *file = (MemFile *) safe_malloc(sizeof(MemFile));
        char *fileMemory = NULL;
        FILE *tmp = open_memstream(&fileMemory,&(file->usedMem));
        file->fp = tmp;
        file->buffer = fileMemory;
        file->addbuffer = &fileMemory;
        file->addfp = &tmp;
        file->isOpen = 1;
        file->next = NULL;
        file->usedMem = 0;
        file->pathname = (char *) safe_malloc((strlen(pathname)+1) * sizeof(char))

但是 valgrind,当我试图释放我的记忆时,吐出

==7958== Invalid write of size 8
==7958==    at 0x49118C8: _IO_mem_finish (memstream.c:131)
==7958==    by 0x4907FC0: fclose@@GLIBC_2.2.5 (iofclose.c:57)
==7958==    by 0x10B5B0: freeFile (mem.c:419)
==7958==    by 0x10B32E: mem_remove (mem.c:367)
==7958==    by 0x10B678: mem_removeFile (mem.c:441)
==7958==    by 0x10B61D: freeMemory (mem.c:431)
==7958==    by 0x10D472: main (newserver.c:458)
==7958==  Address 0x5677cd0 is in a rw- anonymous segment
==7958== 
==7958== Invalid read of size 8
==7958==    at 0x49118D2: _IO_mem_finish (memstream.c:133)
==7958==    by 0x4907FC0: fclose@@GLIBC_2.2.5 (iofclose.c:57)
==7958==    by 0x10B5B0: freeFile (mem.c:419)
==7958==    by 0x10B32E: mem_remove (mem.c:367)
==7958==    by 0x10B678: mem_removeFile (mem.c:441)
==7958==    by 0x10B61D: freeMemory (mem.c:431)
==7958==    by 0x10D472: main (newserver.c:458)
==7958==  Address 0x5677cd0 is in a rw- anonymous segment
==7958== 
==7958== Invalid free() / delete / delete[] / realloc()
==7958==    at 0x483CA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==7958==    by 0x10B5D8: freeFile (mem.c:422)
==7958==    by 0x10B32E: mem_remove (mem.c:367)
==7958==    by 0x10B678: mem_removeFile (mem.c:441)
==7958==    by 0x10B61D: freeMemory (mem.c:431)
==7958==    by 0x10D472: main (newserver.c:458)
==7958==  Address 0x4a7a788 is 8 bytes inside a block of size 104 alloc'd
==7958==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==7958==    by 0x10E13F: safe_malloc (utils.c:7)
==7958==    by 0x10AADC: mem_createFile (mem.c:108)
==7958==    by 0x10BC33: doJob (newserver.c:71)
==7958==    by 0x10CC26: worker (newserver.c:298)
==7958==    by 0x4869608: start_thread (pthread_create.c:477)
==7958==    by 0x49A5292: clone (clone.S:95)
==7958== 
Exiting==7958== 
==7958== HEAP SUMMARY:
==7958==     in use at exit: 42 bytes in 1 blocks
==7958==   total heap usage: 46 allocs, 46 frees, 27,179 bytes allocated
==7958== 
==7958== 42 bytes in 1 blocks are definitely lost in loss record 1 of 1
==7958==    at 0x483DFAF: realloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==7958==    by 0x49118C7: _IO_mem_finish (memstream.c:131)
==7958==    by 0x4907FC0: fclose@@GLIBC_2.2.5 (iofclose.c:57)
==7958==    by 0x10B5B0: freeFile (mem.c:419)
==7958==    by 0x10B32E: mem_remove (mem.c:367)
==7958==    by 0x10B678: mem_removeFile (mem.c:441)
==7958==    by 0x10B61D: freeMemory (mem.c:431)
==7958==    by 0x10D472: main (newserver.c:458)
==7958== 
==7958== LEAK SUMMARY:
==7958==    definitely lost: 42 bytes in 1 blocks
==7958==    indirectly lost: 0 bytes in 0 blocks
==7958==      possibly lost: 0 bytes in 0 blocks
==7958==    still reachable: 0 bytes in 0 blocks
==7958==         suppressed: 0 bytes in 0 blocks
==7958== 
==7958== For lists of detected and suppressed errors, rerun with: -s
==7958== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

我确实已经尝试了所有方法,我什至必须消除所有内存泄漏,但仍然有无效的读取和写入。已经一个多星期了,我刚刚因为纯粹的愤怒而打破了我的办公桌。 这是释放结构元素的函数

int freeFile(MemFile *file){
    if (file == NULL){
        return -1;
    }
    freeifalloc(file->pathname);
    if(file->fp != NULL){
        fclose(file->fp);
        file->fp = NULL;
    }
    freeifalloc(&(file->buffer));
    //freeifalloc(file->fp->_IO_buf_base);
    //pthread_mutex_destroy(&(file->fileLock));
    freeifalloc(file);
    return 1;
}

发送帮助。

内存文件结构

typedef struct fl{

    FILE *fp;
    char *buffer;
    char **addbuffer;
    FILE **addfp;
    char *pathname;
    size_t usedMem;
    int isOpen;
    struct fl *next;
    pthread_mutex_t fileLock;


}MemFile;

freeifalloc

#define freeifalloc(pointer) if(pointer != NULL) {free(pointer); pointer == NULL;}

临时变量是不必要的,是您问题的根源。

//first, allocate your struct
MemFile *file = (MemFile *) safe_malloc(sizeof(MemFile));
//if (!file) error

//you have to zero it out, because in case of an error,
//you probably call the free function, therefore 
//the (pointer) fields have to point to NULL
memset(file, 0, sizeof(MemFile));

file->fp = open_memstream(&file->buffer, &file->usedMem);
//if (!file->fp) error

file->addBuffer = &file->buffer; //what is addBuffer, is this really necessary?
file->addfp = &file->fp; //same here, why?

file->isOpen = 1;
file->next = NULL;

//usedMem is set by open_memstream
//file->usedMem = 0;

//this is also different from your statement
//sizeof(char) equals per standard to 1
file->pathname = (char*) safe_malloc(strlen(pathname)+1);

//there is no no need to set the pointer to NULL
//you free the file anyway, so what's the point?
#define freeifalloc(pointer) if (pointer) free(pointer)

// isn't this much cleaner?
int freeFile(MemFile *file){
    if (!file) 
        return -1;
    
    if (file->pathname)
        free(file->pathname);

    if (file->fp)
        fclose(file->fp);
        
    if (file->buffer)
        free(file->buffer);
        
    if (file)
        free(file);
        
    return 1;
}