Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
移动指针后C中的内存泄漏问题(到底释放了什么?)_C_Memory Management_Memory Leaks_Malloc - Fatal编程技术网

移动指针后C中的内存泄漏问题(到底释放了什么?)

移动指针后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

我意识到下面的代码示例是你永远不应该做的事情。我的问题只是一个有趣的问题。如果分配一个内存块,然后移动指针(no),当释放内存时,释放的内存块的大小是多少,它在内存中的什么位置?以下是精心设计的代码片段:

#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位值的结尾,如分配的内存大小,或链接列表中的链接。这取决于实施情况。不管细节如何,它都会使你的程序崩溃。作为思南点