移动指针后C中的内存泄漏问题(究竟是什么解除分配?)

Mar*_*rio 9 c malloc memory-leaks memory-management

我意识到下面的代码示例是你永远不应该做的事情.我的问题只是一个有趣的问题.如果你分配一块内存,然后移动指针(一个禁忌),当你释放内存时,释放的块的大小是多少,内存在哪里?这是人为的代码片段:

#include <stdio.h>
#include <string.h>

int main(void) {
    char* s = malloc(1024);
    strcpy(s, "Some string");
    // Advance the pointer...
    s += 5;
    // Prints "string"
    printf("%s\n", s);
    /*
     * What exactly are the beginning and end points of the memory 
     * block now being deallocated?
     */
    free(s);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这就是我认为我发生的事情.被释放的内存块以保存字符串"s"的字节开头.持有"Some"的5个字节现在丢失了.

我想知道的是:5个字节在内存中的位置是否紧跟原始1024字节的末尾,也就是说,它们是否只是单独存在?

任何人都知道编译器的作用是什么?这是不确定的?

谢谢.

Sin*_*nür 18

不能传递,这不是从获得的指针malloc,callocreallocfree(除NULL).

C FAQ中的问题7.19与您的问题相关.

这里解释了调用未定义行为后果.


Dav*_*ley 7

它是标准中未定义的行为,因此您不能依赖任何东西.

请记住,块是人为分隔的内存区域,不会自动显示.有必要跟踪块,以释放所有必要的东西,仅此而已.没有可能的终止,比如C字符串,因为没有值或值组合可以保证不在块内.

最后我看,有两个基本的实现实践.

一种方法是保留已分配块的单独记录以及分配的地址.free()函数查找块以查看要释放的内容.在这种情况下,它很可能根本找不到它,并且很可能什么都不做.内存泄漏.但是,没有任何保证.

一种是在分配地址之前将块信息保存在存储器的一部分中.在这种情况下,free()使用块的一部分作为块描述符,并且根据存储的内容(可能是任何内容),它将释放一些东西.它可能是一个太小的区域,也可能是一个太大的区域.很可能是堆腐败.

因此,我预计内存泄漏(没有任何内容被释放)或堆损坏(太多标记为免费,然后重新分配).


Meh*_*ari 5

是的,这是未定义的行为.你基本上是在释放你没有的指针malloc.

  • 未定义的行为意味着"任何事情都可能发生".从将您的机器与您自己一起吹到正常工作. (2认同)
  • 我们在工作中用于未定义行为的常用习语是"给妈妈发邮件" (2认同)