Malloc-释放后使用内存未触发错误
Malloc- Error not triggered for using memory after freeing
下面是我正在试用的C程序。它根据用户输入为所需数量的元素分配内存,为用户获取元素,打印元素和总和。
我在使用 ptr 之前使用 free
函数释放分配的内存。但是,它没有抛出任何错误,我能够 compile/run,成功地打印数组和总和。我对 malloc 和 free 的理解是,如果我们释放分配的内存并尝试访问它,它应该在编译时抛出错误吗?请澄清这个疑问。
谢谢。
#include<stdio.h>
#include<stdlib.h>
int main(void){
int num=0;
int *ptr=NULL;
int sum=0;
printf("Enter number of elements in an array: \n");
scanf("%d",&num);
ptr = (int *)malloc(num*sizeof(int));
if (ptr==NULL){
printf("Error: unable to allocate memory\n");
exit(EXIT_FAILURE);
}
free(ptr); //ERROR NOT TRIGGERED
printf("Enter the elements of the array: \n");
for(int i=0;i<num;i++){
scanf("%d",(ptr+i));
sum += *(ptr+i);
}
printf("\nArray Elements are: \n");
for(int i=0;i<num;i++){
printf("%d ",*(ptr+i));
}
printf("\nSum of array elements are: %d\n", sum);
return 0;
}
这是未定义的行为。 (因为您正在尝试访问一些已经释放的内存。这可能会使您的程序立即崩溃。或者它可能看起来工作得很好,但您不应该依赖它。)。
而且不,它没有。你在这里独自一人。基本上你必须跟踪你是否正在使用已经释放的内存。因为它是未定义的行为 - 你必须避免它。
另外,你预料到释放后会出现错误。不是这种情况。您可以在任何地方释放它(除非您还没有释放它)。编译器不会抱怨您将在此之后使用它 - 所以 不要调用 free
。
既然你已经成功分配了内存,那么free
绝对没有理由触发错误。但是,之后使用指针是 未定义的行为,这意味着任何事情都可能发生,包括正常工作、崩溃、格式化硬盘或将令人反感的图像发送到老板的电子邮件中。当然,最后两件事永远不会发生,但 C 规范中没有任何内容说它不能。未定义的行为是未定义的。
在指针上调用free
基本上意味着您保证不再使用该内存。如果你违背了这个承诺,那么,后果自负。
能编译出来就不奇怪了。如果出错,它将在运行时出错。
Using/accessing 释放后分配的内存是未定义的行为。
来自C Standards#J.2 Undefined behavior:
The value of a pointer that refers to space deallocated by a call to the free or realloc function is used (7.22.3).
检查以下内容:
附加:
Do not cast the return value of malloc
.
只是为已经给出的很好的答案添加一个稍微不同的观点:
您的 预期 可能会抛出错误和错误可能来自具有主动内存管理(例如引用计数或垃圾收集)、复杂对象类型(例如数组对象)的熟悉语言、键值哈希表)和引用实体(对象、结构、函数、变量等)的变量。
关于 c 的重要一点是,与许多其他流行语言(比如 Java 或 Javascript 或 Python 等脚本语言相比,它是相当低级(编译为特定于平台的操作!)并且因此 1) 没有一种机制来监视特定指令是否安全地操作内存(没有运行时环境除了编译的内容) 和 2) 在 c 中,指针的值不是对实体的引用,而是内存地址 ,并且取消引用地址始终是有效的操作或在那里分配一个新值
在您的简单情况下,编译器可能会预见到问题并发出警告(实际上有内存调试工具可以帮助解决这个问题;例如 valgrind)。但是可以想象在读出之前将指针设置为不同的位置,或者作为复杂条件表达式的结果这样做。编译器通常很难在编译时捕获此类错误。
您可能遇到的一个相关运行时错误是由操作系统强加的。如果您尝试访问为您的程序分配的内存之外的内存,您的程序可能会由于操作系统内存划分而退出并出现 分段错误 。
无论如何,我认为这可能会提供一些背景知识,说明为什么访问释放的内存不仅仅是 undefined 是神秘的。这是语言简单的结果。
下面是我正在试用的C程序。它根据用户输入为所需数量的元素分配内存,为用户获取元素,打印元素和总和。
我在使用 ptr 之前使用 free
函数释放分配的内存。但是,它没有抛出任何错误,我能够 compile/run,成功地打印数组和总和。我对 malloc 和 free 的理解是,如果我们释放分配的内存并尝试访问它,它应该在编译时抛出错误吗?请澄清这个疑问。
谢谢。
#include<stdio.h>
#include<stdlib.h>
int main(void){
int num=0;
int *ptr=NULL;
int sum=0;
printf("Enter number of elements in an array: \n");
scanf("%d",&num);
ptr = (int *)malloc(num*sizeof(int));
if (ptr==NULL){
printf("Error: unable to allocate memory\n");
exit(EXIT_FAILURE);
}
free(ptr); //ERROR NOT TRIGGERED
printf("Enter the elements of the array: \n");
for(int i=0;i<num;i++){
scanf("%d",(ptr+i));
sum += *(ptr+i);
}
printf("\nArray Elements are: \n");
for(int i=0;i<num;i++){
printf("%d ",*(ptr+i));
}
printf("\nSum of array elements are: %d\n", sum);
return 0;
}
这是未定义的行为。 (因为您正在尝试访问一些已经释放的内存。这可能会使您的程序立即崩溃。或者它可能看起来工作得很好,但您不应该依赖它。)。
而且不,它没有。你在这里独自一人。基本上你必须跟踪你是否正在使用已经释放的内存。因为它是未定义的行为 - 你必须避免它。
另外,你预料到释放后会出现错误。不是这种情况。您可以在任何地方释放它(除非您还没有释放它)。编译器不会抱怨您将在此之后使用它 - 所以 不要调用 free
。
既然你已经成功分配了内存,那么free
绝对没有理由触发错误。但是,之后使用指针是 未定义的行为,这意味着任何事情都可能发生,包括正常工作、崩溃、格式化硬盘或将令人反感的图像发送到老板的电子邮件中。当然,最后两件事永远不会发生,但 C 规范中没有任何内容说它不能。未定义的行为是未定义的。
在指针上调用free
基本上意味着您保证不再使用该内存。如果你违背了这个承诺,那么,后果自负。
能编译出来就不奇怪了。如果出错,它将在运行时出错。
Using/accessing 释放后分配的内存是未定义的行为。
来自C Standards#J.2 Undefined behavior:
The value of a pointer that refers to space deallocated by a call to the free or realloc function is used (7.22.3).
检查以下内容:
附加:
Do not cast the return value of malloc
.
只是为已经给出的很好的答案添加一个稍微不同的观点:
您的 预期 可能会抛出错误和错误可能来自具有主动内存管理(例如引用计数或垃圾收集)、复杂对象类型(例如数组对象)的熟悉语言、键值哈希表)和引用实体(对象、结构、函数、变量等)的变量。
关于 c 的重要一点是,与许多其他流行语言(比如 Java 或 Javascript 或 Python 等脚本语言相比,它是相当低级(编译为特定于平台的操作!)并且因此 1) 没有一种机制来监视特定指令是否安全地操作内存(没有运行时环境除了编译的内容) 和 2) 在 c 中,指针的值不是对实体的引用,而是内存地址 ,并且取消引用地址始终是有效的操作或在那里分配一个新值
在您的简单情况下,编译器可能会预见到问题并发出警告(实际上有内存调试工具可以帮助解决这个问题;例如 valgrind)。但是可以想象在读出之前将指针设置为不同的位置,或者作为复杂条件表达式的结果这样做。编译器通常很难在编译时捕获此类错误。
您可能遇到的一个相关运行时错误是由操作系统强加的。如果您尝试访问为您的程序分配的内存之外的内存,您的程序可能会由于操作系统内存划分而退出并出现 分段错误 。
无论如何,我认为这可能会提供一些背景知识,说明为什么访问释放的内存不仅仅是 undefined 是神秘的。这是语言简单的结果。