以下是我正在尝试的C程序。它根据用户输入为所需数量的元素分配内存,为用户获取元素,打印元素和元素。总和。
在使用ptr之前,我使用free
函数释放分配的内存。但是,它没有抛出任何错误,我能够成功编译/运行,打印数组和总和。我对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;
}
答案 0 :(得分:4)
由于您已成功分配内存,因此free
绝对没有理由触发错误。但是,在此之后使用指针是未定义的行为,这意味着可能发生任何事情,包括正常工作,崩溃,格式化硬盘或向您的老板电子邮件发送令人反感的图像。当然,最后两件事永远不会发生,但C规范中没有任何内容表明它不会发生。未定义的行为未定义。
在指针上调用free
基本上意味着你保证不再使用内存。如果你打破了这个承诺,那么就要承担后果。
它编译并不奇怪。如果出现这种情况,它将在运行时执行此操作。
答案 1 :(得分:3)
在释放后使用/访问已分配的内存是未定义的行为。
来自C Standards#J.2 Undefined behavior:
使用指向通过调用free或realloc函数解除分配的空间的指针的值(7.22.3)。
检查以下内容:
其他:
答案 2 :(得分:0)
这是未定义的行为。 (因为你试图访问已经释放的一些内存。这可能会立即崩溃你的程序。或者看起来工作得很好,但你不应该依赖它。)。
不,它不。你在这里独自一人。基本上你必须跟踪你是否使用已经释放的内存。因为它是未定义的行为 - 你必须避免它。
此外,您已经预料到释放它时会发生错误。不是这种情况。你可以在任何地方释放它(除非你没有释放它)。编译器不会抱怨您将在此之后使用它 - 所以不要调用free
。
答案 3 :(得分:0)
只是为已经给出的好答案添加一个稍微不同的视角:
您的期望该错误和错误可能来自熟悉的语言,这些语言具有活动的内存管理(例如引用计数或垃圾回收),复杂的对象类型(例如数组对象,键值哈希)表),以及对实体(对象,结构,函数,变量等)的引用的变量。
要理解c的重要一点是,与许多其他流行语言(比如Java或Javascript或Python等脚本语言)相比,它是相当低级的(编译为特定于平台的操作!)并且因为这个 1)没有一种机制可以观察特定指令是否安全地操作内存(除了编译的内容没有运行时环境)和 2)在c中,a的值指针不是对实体的引用,而是内存地址,并且它总是一个有效的操作来取消引用地址或在那里分配新值
在您的简单情况下,编译器可能会预测到问题并发出警告(实际上,内存调试工具可以帮助解决这个问题;例如,valgrind)。但是可以想象在将其读出之前将指针设置为不同的位置,或者将其作为复杂条件表达式的结果。编译器通常很难在编译时捕获这种类型的错误。
您可能遇到的一个相关运行时错误是由操作系统强加的。如果您尝试超出为程序分配的内存,则由于操作系统内存分区,您的程序可能会因分段错误退出。
无论如何,我认为这可能会提供一些背景知识,为什么访问释放的内存不仅仅是 undefined 是神秘的。这是语言简单的结果。