2016-01-02 60 views
13

https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html瞭解GCC 5的_GLIBCXX_USE_CXX11_ABI或新ABI

我遇到了崩潰/ Valgrind的問題與使用上GCC 5的std :: string上面的鏈接提示,有在ABI開始GCC 5.x的變化。 libstd ++的新默認ABI是C++ 11/14 ...,它與舊的ABI不兼容。有一種方法可以使用定義來選擇較早的ABI。

我想了解ABI之間有什麼區別,還沒有找到細節。我想幫助理解:

  1. std :: string需要解決什麼樣的問題才能與新的ABI兼容?它們是否與寫入相關?
  2. 這些變化會影響較早的ABI嗎?
  3. 讓_GLIBCXX_USE_CXX11_ABI工作的任何提示?

關於我遇到的問題的更多細節(https://github.com/YasserAsmi/jvar/issues/21)該項目在GCC 4.8和Clang中運行良好。與海灣合作委員會,同樣的代碼拒絕運行:

x_misc(33112,0x7fff728c2000) malloc: *** error for object 0x7fd639c034cc: pointer being freed was not allocated 
*** set a breakpoint in malloc_error_break to debug 
Abort trap: 6 

這裏是一個局部Valgrind的輸出:

==33027== Invalid read of size 1 
==33027== at 0x1006F78BA: _platform_memmove$VARIANT$Nehalem (in /usr/lib/system/libsystem_platform.dylib) 
==33027== by 0x100009388: jvar::Variant::toString[abi:cxx11]() const (in bin/ex_misc) 
==33027== by 0x1000023A7: bugreport() (in bin/ex_misc) 
==33027== by 0x1000133B8: main (in bin/ex_misc) 

該項目採用的std :: string,並有一些自定義的內存管理。它正在做一些非典型但有效的操作,使用放置新的構造函數等。我試圖更好地理解API會影響什麼樣的代碼,以及如何修復它 - 一個開始的地方。

+0

如果您一致地編譯所有對象(使用相同的ABI),那麼您得到的錯誤是由於程序中的錯誤或(更不可能)是新ABI實現中的實際錯誤。在任何一種情況下,都可以將其用於一個小型測試用例併發布到此處([MCVE])。 – davmac

回答

7
  1. 舊的std::string不符合C++ 11,因爲該標準禁止寫時拷貝實現。沒有辦法在不破壞ABI的情況下創建符合std::string的標準,所以他們用一種方法返回到不符合ABI兼容性的版本。

  2. 是的。

  3. 確保程序中的所有翻譯單元使用相同的值_GLIBCXX_USE_CXX11_ABI,並且您應該沒問題。如果您將它們混合在翻譯單元中,您肯定會遇到問題。您可能可能是好的,如果您在不相互溝通string s的不同翻譯單位中具有不同的定義值。

+0

在#1上,舊的代碼與新的ABI有什麼區別?我可以在舊的代碼中使用std :: strings來查找並修復它?謝謝 – YasserAsmi

+1

很好的答案。在Debian中,我們使用_recompiling everything_按照第3點。請參閱[更多wiki的條目](https://wiki.debian.org/GCC5)。 –

+1

@YasserAsmi沒有什麼可以解決的,新的ABI只需要你連接在一起的所有東西來使用相同的ABI。 – nos

4

有COW和非COW字符串之間例如一個有趣的差異:)由some_string和Foo指向相同的內存返回

std::string some_string; 
std::string foo() 
{ 
    return some_string; 
} 

char const *s = foo().c_str(); 
printf("%s\n",s); 

這與COW字符串爲c_str(工作但是當它不是COW時,一旦std :: string被foo返回的字符串被銷燬,s就會失效。

從樣本中你應該看看這個方向。

+4

K ...但是不是這樣還是未定義的行爲通過嘗試使用從'foo()'返回值創建的臨時std :: string中提取的指針?由於COW是允許的,但不是必需的,你不能認爲它在起作用。 –

+2

這是未定義的行爲,但當字符串是COW並且比使用非COW字符串時,它可能導致隱藏的錯誤。 – Artyom

+2

那你就是在指責錯誤的東西。隱藏的bug是因爲未定義的行爲,而不是COW的存在。與導致(或不導致)程序崩潰的解除引用'nullptr'不同。 –