2015-12-22 21 views
1

我有程序使用std::string,但是memmove std :: string`實例。在gcc中使用舊的std :: string

它工作正常,直到gcc 5.1。

但是,這不再起gcc 5.3的作用。我認爲開發者最終用內部指針做了SSO。

我肯定會解決這個問題,但有沒有簡單的方法來解決它的一些定義或編譯?

代碼類似於此:

// MyClass have std::string inside 
MyClass *a = malloc(MAX * sizeof(MyClass)); 
// ... 
// placement new on a[0] 
// ... 
memmove(&a[1], &a[0], sizeof(MyClass)); 
// ... 
process(a[1]); 

這是舊代碼,請不要評論有關malloc使用。

我會重構或切換到std::vector,但我希望代碼工作,直到我這樣做。

+0

你真的應該做的不是強制編譯器使用你的代碼,而是重構你的代碼,以便它能夠與現代C++編譯器一起工作(並且我的意思是說過去15年左右) 。這意味着不使用'malloc'來分配對象,或者使用舊的C內存複製功能來複制對象。 –

+0

我想要代碼工作,直到我重構。 – Nick

+1

您可以在舊代碼編譯器的「真正位置」處重新構建新代碼 – dewaffled

回答

1

您正在經歷未定義行爲的影響,但我認爲您知道這一點。您不能依賴字節式複製非POD響應的效果。不是可以複製的類型,編譯器可以自由地改變這種行爲。

我認爲有可能爲您的類定義一個安全的過載memmove作爲參數並在其中使用複製構造函數。我不知道這是否完全合法,但是您似乎在命名空間std中使用C函數而不是C++版本,所以至少您不會更改不允許的名稱空間std

void memmove(MyClass* a, MyClass* b, size_t) 
{ 
    *a = *b; 
} 

嚴格地說,我認爲這仍然是不確定的行爲,因爲C++標準的17.6.4.3規定

如果程序聲明或在其被 保留上下文定義了一個名字,除本條款明確允許外,其行爲不明確。

此外,C庫中的所有名稱均爲保留名稱,不得由程序使用(17.6.4.3.2)。實際上,我認爲這會起作用。

您可能需要編譯​​以防止gcc全局替換memmove。如果覆蓋該功能是非法的,可以用LD_PRELOAD動態替換。

這是一個黑客解決方案!你的代碼可能仍然不起作用,因爲編譯器假定你是memmove它是一個POD/TriviallyCopyable對象,並用它來進行一些優化,例如,通過假設在memmove之後,兩個對象都由相同的字節表示。當您使用複製構造函數重新實現memmove時,這會被破壞。

相關問題