Malloc-释放后使用内存时未触发错误

时间:2018-01-04 05:25:09

标签: c malloc free

以下是我正在尝试的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;
}

4 个答案:

答案 0 :(得分:4)

由于您已成功分配内存,因此free绝对没有理由触发错误。但是,在此之后使用指针是未定义的行为,这意味着可能发生任何事情,包括正常工作,崩溃,格式化硬盘或向您的老板电子邮件发送令人反感的图像。当然,最后两件事永远不会发生,但C规范中没有任何内容表明它不会发生。未定义的行为未定义。

在指针上调用free基本上意味着你保证不再使用内存。如果你打破了这个承诺,那么就要承担后果。

它编译并不奇怪。如果出现这种情况,它将在运行时执行此操作。

答案 1 :(得分:3)

在释放后使用/访问已分配的内存是未定义的行为。

来自C Standards#J.2 Undefined behavior

  

使用指向通过调用free或realloc函数解除分配的空间的指针的值(7.22.3)。

检查以下内容:

1. Freeing memory

2. Using freed memory

其他:

Do not cast the return value of malloc.

答案 2 :(得分:0)

这是未定义的行为。 (因为你试图访问已经释放的一些内存。这可能会立即崩溃你的程序。或者看起来工作得很好,但你不应该依赖它。)。

不,它不。你在这里独自一人。基本上你必须跟踪你是否使用已经释放的内存。因为它是未定义的行为 - 你必须避免它。

此外,您已经预料到释放它时会发生错误。不是这种情况。你可以在任何地方释放它(除非你没有释放它)。编译器不会抱怨您将在此之后使用它 - 所以不要调用free

答案 3 :(得分:0)

只是为已经给出的好答案添加一个稍微不同的视角:

您的期望该错误和错误可能来自熟悉的语言,这些语言具有活动的内存管理(例如引用计数或垃圾回收),复杂的对象类型(例如数组对象,键值哈希)表),以及对实体(对象,结构,函数,变量等)的引用的变量。

要理解c的重要一点是,与许多其他流行语言(比如Java或Javascript或Python等脚本语言)相比,它是相当低级的(编译为特定于平台的操作!)并且因为这个 1)没有一种机制可以观察特定指令是否安全地操作内存(除了编​​译的内容没有运行时环境)和 2)在c中,a的值指针不是对实体的引用,而是内存地址,并且它总是一个有效的操作来取消引用地址或在那里分配新值

在您的简单情况下,编译器可能会预测到问题并发出警告(实际上,内存调试工具可以帮助解决这个问题;例如,valgrind)。但是可以想象在将其读出之前将指针设置为不同的位置,或者将其作为复杂条件表达式的结果。编译器通常很难在编译时捕获这种类型的错误。

您可能遇到的一个相关运行时错误是由操作系统强加的。如果您尝试超出为程序分配的内存,则由于操作系统内存分区,您的程序可能会因分段错误退出。

无论如何,我认为这可能会提供一些背景知识,为什么访问释放的内存不仅仅是 undefined 是神秘的。这是语言简单的结果。