2015-05-03 43 views
3

我有一個奇怪的問題有時與GCC(4.6.4,Ubuntu 12.04),我用它來編譯一個巨大的項目(數百個文件和數十萬行代碼),但我最近發現了一些東西。經過一定的編譯(似乎是隨機發生的),我得到不同,錯誤地編了一段特定的代碼,在我的代碼導致未定義的行爲:兩個GCC編譯相同的輸入,生成兩個不同的代碼(第二個錯誤)

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 

的制定者似乎得到內聯很可能因爲編譯標誌-02,:

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

但是這不是問題。真正的問題是成員someOtherMember0x278c是正確的(第一種情況),但0x27d4是不正確的(第二種情況)的偏移量,這顯然最終修改類的完全不同的成員。這是爲什麼發生?我錯過了什麼? (另外,我不知道我可以發佈什麼其他相關信息,所以請問)。請記住,在再次編譯項目(完全重新編譯或僅編譯修改的文件)時,會發生這種情況,沒有修改受影響的文件(或帶有使用的類的文件)。例如,在一個完全不相關的文件中添加一個簡單的printf()可能會觸發這種行爲,或者在事件發生時使其消失。 我是否應該將此歸咎於-O2?如果沒有優化標記,我無法重現它,因爲這完全是隨機的。 我使用使-j 8,這種情況即使在清潔生成文件夾,但不一定這樣做

+0

你可能有一個附近的未定義的行爲。 – kiwixz

+6

這聽起來像你違反了一個定義規則,但我不能告訴你如何,或者以什麼具體方式導致你的問題。 –

+4

太難猜測了。我們可能需要一個[MCVE](http://stackoverflow.com/help/mcve) – AndyG

回答

3

正如評論所說,你可能有一些後才發生的條件類的定義在各種.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 
+0

我遇到問題了。對於除了一個.o文件以外的所有文件,我在當前上下文中得到「無符號」SomeClass「,只在SomeClass.cpp.o中得到了預期的結果,儘管包含SomeClass.h(其中包含我有問題的類的定義)在許多其他.cpp文件中。不知道是否值得一提,但我正在使用預編譯頭文件 – Shocker

+0

預編譯頭文件爲問題添加了另一個維度,但由於我從未使用它們,所以我無法確定它們如何影響此測試。也許你可以嘗試在沒有PCH的情況下構建並查看會發生什麼? –

+0

不幸的是,目前沒有PCH就無法編譯項目,需要很多修改。但我確實有各種#pragma包,我會嘗試刪除它們,因爲它是更快的行動方式 – Shocker

相關問題