2017-11-23 3 views
1

folgendes Programm vor:LTO verursacht Absturz in Standardbibliothek

#include <iostream> 
#include <string> 

int main() 
{ 
     std::string s; 
     std::getline(std::cin, s); 
     return 0; 
} 

Ich versuche es mit verschiedenen Flaggen zu bauen und als echo foo | ./prog laufen.

Wenn ich es mit clang 5.0 oder gcc 7.1 (oder 7.2) mit Optimierung von -O0 bis -O3 erstellen, funktioniert es wie erwartet. Aber wenn ich -flto auf eine dieser Konfigurationen hinzufügen, stürzt es ab sofort mit der folgenden Backtrace:

/lib64/libc.so.6(+0x721af)[0x7f596b08e1af] 
/lib64/libc.so.6(+0x77706)[0x7f596b093706] 
/lib64/libc.so.6(+0x78453)[0x7f596b094453] 
/usr/lib64/libstdc++.so.6(_ZNSs7reserveEm+0x85)[0x7f596b9ac055] 
/usr/lib64/libstdc++.so.6(_ZSt7getlineIcSt11char_traitsIcESaIcEERSt13basic_istreamIT_T0_ES7_RSbIS4_S5_T1_ES4_+0x175)[0x7f596b984c05] 
./a.out[0x400d7d] 
./a.out[0x400c32] 
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f596b03c6e5] 
./a.out[0x400ab9] 

Valgrind meldet das gleiche in einer leicht lesbarer Weise:

==30863== Invalid free()/delete/delete[]/realloc() 
==30863== at 0x4C2A8DC: operator delete(void*) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) 
==30863== by 0x4F0E054: std::string::reserve(unsigned long) (in /usr/lib64/libstdc++.so.6.0.24) 
==30863== by 0x4EE6C04: std::basic_istream<char, std::char_traits<char> >& std::getline<char, std::char_traits<char>, std::allocator<char> >(std::basic_istream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, char) (in /usr/lib64/libstdc++.so.6.0.24) 
==30863== by 0x40091B: main (in /path/to/prog) 
==30863== Address 0x6011c0 is 0 bytes inside data symbol "_ZNSs4_Rep20_S_empty_rep_storageE" 

Auch funktioniert es OK mit --std=c++14 und darunter sogar mit aktiviertem LTO.

Also, was ist das Problem? Ist es ein Fehler in der LTO-Implementierung für C++ 17 in beiden Compilern? Oder nur die libstdc++ ist mit falschen Flags kompiliert? Ich benutze opensuse 42.3 und die Standardbibliothek wird von den Speichern installiert.

Kann es irgendwie bearbeitet werden?

Antwort

1

Für gcc sieht das wie dieser Bug aus: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82172.

Es gibt eine Reihe von Problemumgehungen, siehe https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82172#c3. Einer von ihnen ist -D_GLIBCXX_USE_CXX11_ABI=1 zu verwenden:

g++ -D_GLIBCXX_USE_CXX11_ABI=1 --std=c++17 -flto prog.cpp 

Siehe auch das gleiche Problem hier flto crash with gcc7.2.

+0

Vielen Dank für die Antwort! Ihre Links zeigten mir die richtige Richtung, also löste ich das Problem und fügte meine eigene Antwort mit vollständiger Beschreibung hinzu. – Sergey

0

Nach Links von ks1322, landete ich endlich auf binutils Bug page, die beschreibt die Wurzel des Problems.

Der Fehler wurde schließlich in binutils 2.30 behoben und nach binutils 2.29 und 2.28 zurückportiert. Die Aktualisierung auf binutils 2.29 behebt das Testbeispiel, aber mein tatsächlicher Build war immer noch betroffen.

Ich fand heraus, dass eine der Abhängigkeiten meines Projekts (ich verwende CMake und external project module) ohne LTO erstellt wurde. Das Hinzufügen von -flto zu allen Abhängigkeiten und die Verwendung eines geeigneten Archivers (d. H. gcc-ar anstelle von ar) lösten das Problem vollständig.

Verwandte Themen