【问题标题】:Freeing memory as man suggests yields errors in valgrind按照人的建议释放内存会在 valgrind 中产生错误
【发布时间】:2021-09-07 00:04:52
【问题描述】:

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

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;}

【问题讨论】:

  • MemFileopen_memstreamfreeifalloc 是什么?
  • file->addbuffer = &fileMemory;ile->addfp = &tmp; 看起来很可疑。您确定在引用的变量无效后不使用它们吗?请发帖Minimal, Reproducible Example
  • 这里没有足够的信息来看看你可能做错了什么。请使用minimal reproducible example 更新您的问题。
  • @MikeCAT 它们并没有真正使用,它们只是以防万一我需要它们,我使用 fread 和 fwrite 从 FILE * 写入和读取

标签: c memory valgrind


【解决方案1】:

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

//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;
}

【讨论】:

  • 我正在执行它,先生,如果这行得通,我要哭了
  • OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO MY GOD YOU SIR ARE D MAN IT WORKS HOLY MOLLY WOIWEFOIJ EFPOIQWFPOIQWJ FPOQIJGPOQIERPOQIEGJPQOIERGPQOEIRG JOPQEI,顺便说一句,safe_malloc 已经是 0 内存:P,也没有 addBuffer 和 addfp指向 null 的指针只是一个额外的步骤,以确保我已经释放了该内存,但我需要尝试一切才能说“好吧,我找不到错误”。从我的心底,真的,谢谢
  • 您打算如何处理addBufferaddfp 字段?我很好奇。但很高兴它成功了。顺便提一句。 pathname 处于当前状态,只是保留缓冲区,还不是字符串。
  • "没有必要将指针设置为 NULL" 如果代码用于类似模式的构造函数/析构函数中,并且您一遍又一遍地重复使用相同的变量,那么就会出现这种情况。然而,在调用 free() 之前不需要检查指针是否为 NULL。正如友好手册中所预言的那样。
  • @Erdal Küçük 那些是因为我在网上读到,当你想从 open_memstream 中释放缓冲区时,你需要拥有地址本身,它有点成功,但我仍然有那些无效的读写,在某些时候,我很累看到内存泄漏,我已经开始从 file->fp->_IO_buf_base 释放缓冲区,多亏了这个,泄漏在 0 但仍然无效的读写,这些变量在那里,因为毕竟我还没有删除它们。最后我今天学到了一个新东西,打破了一张桌子。快乐但仍然破碎的桌子。
猜你喜欢
  • 2020-12-04
  • 2013-12-23
  • 1970-01-01
  • 2020-08-09
  • 2021-03-29
  • 2012-06-12
  • 1970-01-01
  • 2018-06-04
  • 2016-08-07
相关资源
最近更新 更多