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).

检查以下内容:

1. Freeing memory

2. Using freed memory


附加:

Do not cast the return value of malloc.

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

您的 预期 可能会抛出错误和错误可能来自具有主动内存管理(例如引用计数或垃圾收集)、复杂对象类型(例如数组对象)的熟悉语言、键值哈希表)和引用实体(对象、结构、函数、变量等)的变量。

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

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

您可能遇到的一个相关运行时错误是由操作系统强加的。如果您尝试访问为您的程序分配的内存之外的内存,您的程序可能会由于操作系统内存划分而退出并出现 分段错误

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