int main()
{
char *s1, *sTemp;
s1 = (char*)malloc(sizeof(char)*7);
*(s1 + 0) = 'a';
*(s1 + 1) = 'b';
*(s1 + 2) = 'c';
*(s1 + 3) = 'd';
*(s1 + 4) = 'e';
*(s1 + 5) = 'f';
*(s1 + 6) = '\0';
sTemp = (s1 + 3);
free(sTemp); // shud delete d onwards. But it doesn't !!
return 0;
}
您好,
在 C 上面,代码sTemp
应指向s1
以外的第3个单元格(由'd'占用)
因此,在致电free(sTemp)
时,我希望从此位置开始删除 。
(我故意提到' 某事 ',因为我的实验的动机最初是找出free()ing工作的位置)
但是我在SIGABRT
收到free()
。
free()
如何知道这不是块的开头。相应地,我们只能从块的开始释放内存吗? [他们只是free()
可以接受的自由指针吗? ]
期待回复:)
答案 0 :(得分:7)
从手册页
free()
释放指向的内存空间 到ptr
,一定是 之前的电话回复malloc()
,calloc()
或realloc()
。 否则,或者free(ptr)
已经存在 以前被称为未定义 行为发生。
答案 1 :(得分:3)
关于实际问题“free
如何知道......”:
free
知道它不在块的开头,因为它维护着你不知道的元数据。如果你考虑一下,那就是必然那么,因为否则它只能在一个地址的情况下知道要释放多少内存。
没有指定运行时如何保持分配大小,只是你必须永远传递任何 not 来自free
的指针malloc
家庭的一个功能。
通常这可以通过malloc
分配比所需 [1] 更多的内存,并在内存前面返回的地址中写入一些元数据。 free
然后只看例如ptr[-8]
或其他(实现细节!)来阅读此元数据
然后它可以选择进行一些一致性检查,并且可以确定内存块的大小(可能总是进行一次微不足道的一致性检查,检查指针是否正确对齐)。
在提到之后,请讨好,甚至不要考虑使用这个元数据。
[1] 无论如何它通常都是为了满足对齐要求,并且因为分配器内部(大多数分配器管理固定大小的不同“桶”中的内存),所以如果分配,比方说,4字节,你名义上得到4个字节,但运行时大部分时间确实分配了8或16个字节(你不知道)。
答案 2 :(得分:2)
您只能free()
实际malloc
ed(或calloc
ed,realloc
ed的指针。如果你试图通过传入一个不同的指针(即使是另一个指针的“部分”)来释放一部分内存,那么C运行时将不会高兴(正如你所看到的那样)。
答案 3 :(得分:2)
我认为你无法释放内存,因为free不知道要释放多少内存。你的程序有关于地址malloc()返回的信息,而不是这个空间中的每个地址。所以你可以释放(s1)但是不是免费的(s1 + 3)。也可以在这个例子中将指针作为数组处理: S1 [0] = 'A';
答案 4 :(得分:1)
您只能free()
以前malloc
,calloc
或realloc
编辑过的realloc
内存,正如dlev和Daniel所说的那样。
其原因是依赖于实现,但涉及跟踪已分配内存的方法。
高效的内存分配是一个难题,因为不同的内存分配算法可以很好地工作,具体取决于内存的分配方式:一些小块,其中一半被释放,然后抓取稍大的块等等。
目标是使程序使用的内存块的大小保持最小(通常这个块将是一个连续的虚拟内存块),同时保持该块内空间的使用率极高(几个间隙)在已用的内存段之间。)
请记住,除非free
被编辑,否则无法移动这些块,因此总会留下一些浪费的空间。
为了最大限度地减少浪费,关于(至少)块大小的元数据就在它之前存储。在确定如何处理新请求时,内存分配器可以查看使用的块。如果您选择随机内存位置,无论是先前分配的区域的一部分还是否,此元数据都不会出现,{{1}}将无法确定应该释放的内容。
答案 5 :(得分:0)
你不能以你的方式释放指针,检查这个问题及其答案:Memory Clobbering Error