另一个问题讨论了优化器移除对
从我的理解来看,编译器允许在“as-if”规则下删除或合并动态分配,即如果结果程序的行为与标准中定义的抽象机器相比没有发生变化,则可以进行更改。
我使用clang++和g++及
new
的调用的合法性:编译器是否允许优化堆内存分配?。我已经阅读了这个问题、答案和N3664。从我的理解来看,编译器允许在“as-if”规则下删除或合并动态分配,即如果结果程序的行为与标准中定义的抽象机器相比没有发生变化,则可以进行更改。
我使用clang++和g++及
-O1
优化编译了以下两个文件的程序,但是我不明白如何允许删除这些分配。// main.cpp
#include <cstdio>
extern int g_alloc;
static int* foo(int n)
{
// operator new is globally overridden in the other file.
return new int(n);
}
int main(int argc, char** argv)
{
foo(argc);
foo(argc*2);
printf("allocated: %d\n", g_alloc);
return g_alloc;
}
// new.cpp
#include <cstdio>
#include <cstdlib>
#include <new>
int g_alloc = 0;
void* operator new(size_t n)
{
g_alloc += n;
printf("new %lu\n", n);
return malloc(n);
}
这个想法是通过一个带有副作用的函数覆盖默认的operator new(size_t)
,该函数会打印一条消息并修改一个全局变量,后者被用作退出代码。
副作用不会影响分配本身,但仍然会改变程序的输出。事实上,在没有优化编译的情况下,输出是:
new 4
new 4
allocated: 8
但是一旦启用了优化,输出结果如下:
allocated: 0
使用标准98到17时,结果相同。
编译器如何允许省略这里的分配?它如何符合as-if规则?