提问人:Agiltohr 提问时间:2/15/2023 最后编辑:Eric PostpischilAgiltohr 更新时间:2/15/2023 访问量:146
编译器可以假设 malloc 永远不会返回 NULL 吗?
Can the compiler assume that malloc will never return NULL?
问:
在本视频中提到,编译器可以假设它永远不会返回,并允许相应地进行优化。我从未听说过这个,在 C 标准中也找不到任何参考。谁能告诉我这是否属实,如果是,这种行为是在哪里指定的?malloc
NULL
此时视频中显示的代码为:
if((a = malloc(1024)) == NULL)
printf("We are out of memory!\n");
else
free(a);
答:
4赞
Eric Postpischil
2/15/2023
#1
说话者并不意味着编译器可以假定从不返回 null 指针。它们意味着在所示的特定情况下,编译器可以看到代码的作用,并且可以在不调用的情况下实现它,并且等效地,它可以被优化,就好像在特定情况下从不返回 null 一样。malloc
malloc
malloc
C 标准允许编译器以产生指定可观察行为的任何方式实现代码,即从 C 2018 5.1.2.3 6 开始:
- 对易失性对象的访问严格按照抽象机器的规则进行评估。
- 在程序终止时,写入文件的所有数据应与根据抽象语义执行程序所产生的结果相同。
- 交互式设备的输入和输出动态应按照 7.21.3 的规定进行。这些要求的目的是尽快出现无缓冲或行缓冲的输出,以确保提示消息在程序等待输入之前实际出现。
请注意,这不是可观察行为的一部分。它位于 C 实现内部,这意味着允许编译器优化其行为方式。即使有一个单独的库提供 ,编译器也可以将其视为对 C 实现的辅助,并优化程序中的使用。malloc
malloc
malloc
评论
1赞
wohlstad
2/15/2023
说话者实际上明确表示(大约 1:04:19)编译器可以假设内存是可分配的,因此 malloc 不会返回 NULL。这在我看来是错误的。
2赞
DevSolar
2/15/2023
调用的返回可能远远超出了编译器或库实现的控制范围,除非该库实现本身已优化了系统调用,并已告知编译器它已这样做。目前,在标准范围内如何实现的机制使我无法理解。无论如何,在一般情况下,它不可能是一个有效的优化,因为一般情况下,很可能会返回。malloc()
NULL
malloc()
malloc()
NULL
2赞
Eric Postpischil
2/15/2023
@SupportUkraine:编译器根本不需要调用外部例程。C 标准对 C 实现的要求是它向程序提供 C 2018 7.22.3 中指定的内存管理功能。如果编译器显示“嘿,我可以给你你想要的内存,而无需调用外部”,这是一个有效的优化。想象一下,程序在抽象机器内执行,这就是 C 标准指定它的方式。在该抽象计算机中,程序调用 ,获取指向 1024 字节的指针,...malloc
malloc
malloc
2赞
Eric Postpischil
2/15/2023
...看到指针不为空(因为这个抽象机器在源代码中的此时总是有可用的内存),并调用 .因此,C 标准完全允许程序以这种方式运行。现在,你将如何实现抽象机器的这种行为?您不必调用物理机中的外部设备即可执行此操作。我们知道程序的行为是什么:这个特定的代码没有可观察到的副作用。因此,我们可以通过什么都不做来实现它,包括不调用外部。free
malloc
malloc
3赞
Eric Postpischil
2/15/2023
@SupportUkraine:Clang 进行此优化。
评论
int a = 10; if (a == 10) { a = 5; }
int a = 5;
malloc
malloc()