gpt4 book ai didi

c++ - 两次 GCC 编译相同的输入,生成两个不同的代码(第二个错误)

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:52:39 24 4
gpt4 key购买 nike

我有时会遇到 GCC(4.6.4,Ubuntu 12.04)的奇怪问题,我正在使用它来编译一个巨大的项目(数百个文件和数十万行代码),但我最近发现了一些东西。在某些编译之后(似乎是随机发生的),我得到了一段特定的代码,编译方式不同且错误,导致我的代码出现未定义的行为:

class someDerivedClass : public someBaseClass
{
public:
struct anotherDerived : public anoterBaseClass
{
void SomeMethod()
{
someMember->someSetter(2);
}
}
}

其中“someSetter”定义为:

void someSetter(varType varName) { someOtherMember = varName; }

通常,SomeMethod() 被编译为:

00000000019fd910  mov 0x20(%rdi),%rax 
00000000019fd914 movl $0x2,0x278c(%rax)
00000000019fd91e retq

但有时它会(错误地)编译为:

000000000196e4ee  mov 0x20(%rdi),%rax 
000000000196e4f2 movl $0x2,0x27d4(%rax)
000000000196e4fc retq

setter 似乎是内联的,可能是因为编译标志 -O2:

-std=c++11 -m64 -O2 -ggdb3 -pipe -Wliteral-suffix -fpermissive -fno-fast-math -fno-strength-reduce -fno-delete-null-pointer-checks -fno-strict-aliasing

但这不是问题。真正的问题是成员 someOtherMember 的偏移量,0x278c 是正确的(第一种情况)但是 0x27d4 是不正确的(第二种情况),这显然最终修改了一个完全不同的类(class)成员。为什么会这样?我错过了什么? (另外,我不知道我可以发布哪些其他相关信息,所以问)。请记住,当再次编译项目(完全重新编译或仅编译修改后的文件)时会发生这种情况,没有修改受影响的文件(或具有已用类的文件)。例如,仅在完全不相关的文件中的某处添加一个简单的 printf() 可能会触发此行为或使其在发生时消失。我应该把这简单地归咎于-O2 吗?没有优化标志我无法重现它,因为这完全是随机发生的。我正在使用 ma​​ke -j 8,即使在清理构建文件夹后也会发生这种情况,但不一定只有在这样做之后才会发生

最佳答案

如评论中所述,您可能在各种 .cpp 中使用不同的条件来定义您的类,例如 #pragma pack 或类似的东西在包含您的 .h 之前;当链接器必须选择时,它可能会不确定地选择(因为它希望所有定义都相同)。

为了缩小对问题根源的搜索范围,我会这样做:

  1. 使用调试符号 (-g) 编译整个项目;
  2. 使用gdb根据每个模块确定“有问题”字段的偏移量
  3. 一旦找到不同值的位置,就可以使用 gcc -E 展开所有预处理器内容并查找问题。

作为步骤 2 的辅助工具,您可以使用这个 bash 单行代码(在目标文件所在的目录中运行):

for i in ./*.o; do echo -n "$i: "; gdb -batch -q "$i" -ex "print &((YourClass*)0)->yourField"; done

关于c++ - 两次 GCC 编译相同的输入,生成两个不同的代码(第二个错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30020759/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com