移动指针后C中的内存泄漏问题(到底释放了什么?)
我意识到下面的代码示例是你永远不应该做的事情。我的问题只是一个有趣的问题。如果分配一个内存块,然后移动指针(no),当释放内存时,释放的内存块的大小是多少,它在内存中的什么位置?以下是精心设计的代码片段:移动指针后C中的内存泄漏问题(到底释放了什么?),c,memory-management,memory-leaks,malloc,C,Memory Management,Memory Leaks,Malloc,我意识到下面的代码示例是你永远不应该做的事情。我的问题只是一个有趣的问题。如果分配一个内存块,然后移动指针(no),当释放内存时,释放的内存块的大小是多少,它在内存中的什么位置?以下是精心设计的代码片段: #include <stdio.h> #include <string.h> int main(void) { char* s = malloc(1024); strcpy(s, "Some string"); // Advance the p
#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;
}
#包括
#包括
内部主(空){
char*s=malloc(1024);
strcpy(s,“某些字符串”);
//前进指针。。。
s+=5;
//打印“字符串”
printf(“%s\n”,s);
/*
*记忆的起点和终点到底是什么
*块现在正在被释放?
*/
免费的;
返回0;
}
以下是我认为我发生的事情。正在释放的内存块以保存“string”中字母“s”的字节开始。保存“Some”的5个字节现在丢失
我想知道的是:5个字节在内存中的位置是否紧跟着原来的1024个字节的末尾,或者它们是单独释放的
有人确切知道编译器是做什么的吗?它是未定义的吗
谢谢。是的,这是未定义的行为。您实际上是在释放一个没有
malloc
的指针您不能将一个不是从malloc
、calloc
或realloc
获得的指针传递到free
(除了NULL
)
在C中,FAQ与您的问题相关
解释了。不是编译器做的,而是标准库。该行为未定义。库知道它已将原始
s
分配给您。s+5
未分配给库已知的任何内存块,即使它恰好位于已知块内。因此,它将不起作用。您无法将未从malloc
(或calloc
或realloc
…)获得的指针传递到free
。其中包括从malloc
获得的块偏移量。违反这条规则可能会导致任何事情发生。通常,在最糟糕的时刻,这是最糟糕的可能
进一步说明,如果要截断块,有一种合法的方法:
#include <stdio.h>
#include <string.h>
int main() {
char *new_s;
char *s = malloc(1024);
strcpy(s, "Some string");
new_s = realloc(s, 5);
if (!new_s) {
printf("Out of memory! How did this happen when we were freeing memory? What a cruel world!\n");
abort();
}
s = new_s;
s[4] = 0; // put the null terminator back on
printf("%s\n", s); // prints Some
free(s);
return 0;
}
#包括
#包括
int main(){
字符*新字符;
char*s=malloc(1024);
strcpy(s,“某些字符串”);
新的=realloc(s,5);
如果(!新建){
printf(“内存不足!当我们释放内存时,这是怎么发生的?多么残酷的世界!\n”);
中止();
}
s=新的;
s[4]=0;//重新启用空终止符
printf(“%s\n”,s);//打印一些
免费的;
返回0;
}
realloc
用于放大和缩小内存块,但可以(也可以不)移动内存来放大和缩小内存块
我想知道的是:5个字节在内存中的位置是否紧跟着原来的1024个字节的末尾,或者它们是单独释放的
两者都有。结果是未定义的,因此编译器可以自由地执行其中任何一项,或者执行他们真正想要的任何其他操作。当然(与所有“未定义行为”的情况一样),对于特定的平台和编译器有一个特定的答案,但任何依赖于这种行为的代码都是一个坏主意。补充更正式的答案:我会将其机制与在库中取书(malloc)进行比较,然后连同封面一起撕下几十页(推进指针),然后尝试归还(免费) 您可能会找到一个图书管理员(malloc/free library实现)收回这样一本书,但在很多情况下,我希望您会因为疏忽处理而支付罚款 在C99草案中(我手头上没有最终的C99),有一些关于这个主题的话要说: free函数使
ptr
指向的空间被释放,
即可供进一步分配。如果ptr
是空指针,则不执行任何操作
发生。否则,如果参数与先前返回的指针不匹配
通过calloc
、malloc
或realloc
功能,或者如果空间已
通过调用free
或realloc
解除分配,行为未定义
根据我的经验,未通过
malloc
返回的“指针”的双自由或自由将导致内存损坏和/或崩溃,具体取决于malloc
实现。围栏两侧的安全人员从未使用过这种行为,至少在广泛使用的Doug Lea的malloc
软件包的早期版本中使用过这种行为。简短版本:这是未定义的行为
长篇版本:我检查了答案,发现虽然这是一个坏主意,但似乎没有人有一个可靠的答案。可能是因为它没有定义
我的猜测是,假设大多数实现没有崩溃,它们要么释放1019个字节(在您的示例中),要么释放1024个字节,并在最后五个字节上获得双重释放或类似的释放。从理论上讲,这取决于malloc例程的内部存储表是包含地址和长度,还是包含起始地址和结束地址
无论如何,这显然不是一个好主意。:-) 库实现可能会在返回给您的指针之前放置一些数据结构。然后在
free()
中,它递减指针以获取数据结构,告诉它如何将内存放回空闲池。因此,字符串“Some”开头的5个字节被解释为malloc()
算法使用的struct
的结尾。可能是32位值的结尾,如分配的内存大小,或链接列表中的链接。这取决于实施情况。不管细节如何,它都会使你的程序崩溃。作为思南点