【发布时间】:2018-07-18 09:58:12
【问题描述】:
这让我头疼!我在函数调用期间对堆栈进行了一些实验,我遇到了这个小异常。编译器是 GCC 4.9.2 和 -O1、-O2 或 -O3 优化标志。禁用优化 (-O0) 时不存在该问题。无论是在C++98、C++11还是C++14下编译,结果都是一样的。
在下面的示例中,我假设 CDECL 调用约定用于对 result() 的调用,因此 args 应该从右到左压入堆栈。
#include <iostream>
void result(int a, int b) {
int* pA = &a;
int* pB = &b;
// pA should be equal to pB + sizeof(int) bytes, why does this report "false"
// when optimizations are on?
std::cout << (pA == pB + 1 ? "true" : "false") << '\n';
// this appears to be true if we dump the pointer addresses.
std::cout << pA << ", " << pB + 1 << '\n';
// and still holds water when getting values through indirection.
std::cout << "a: " << *(pB + 1) << " b: " << *pB << '\n';
}
int main(int argc, char** argv)
{
result(10, 20);
return 0;
}
启用优化的示例输出:
false // why?
0x704eca3c088c, 0x704eca3c088c // clearly they're equal
a: 10 b: 20 // and point to the correct arguments on the stack
禁用优化的示例输出:
true
0x7e5bd5f34fdc, 0x7e5bd5f34fdc
a: 10 b: 20
当可以直观地比较它们的相等性并发现它们的相等性时,编译器优化会导致堆栈指针比较失败怎么办,优化与否?
编辑:我相信这个问题与建议的副本 (Is it unspecified behavior to compare pointers to different arrays for equality?) 不同,因为堆栈传统上是作为连续数组实现的(显然有例外 - 一个恰当的例子),并且建议的副本给出了两个不同数组的示例.
【问题讨论】:
-
不同对象之间的指针比较未定义。允许优化器假设未定义的行为永远不会发生。
-
pA 应该等于 pB + sizeof(int) bytes 为什么?为什么应该这样?如果编译器认为合适,则不必将这些值存储在堆栈帧中。
-
这是我的一个假设。我现在明白这是未定义的行为。显然它是未定义的,除非它们是指向同一对象的成员或同一数组的元素的指针。
-
@Barmar 事实上,它保证
false指向不同对象的指针,除了来自一个对象的一个过去指针和另一个未指定的对象的开始指针的特殊情况 -
不知道为什么这被否决了,这对我来说似乎是个好问题并且写得很好
标签: c++ optimization