Abbiamo passato tutto il giorno a indagare su questo errore e i miei colleghi dicono che sembra un bug di linker o di libreria. Non ho mai avuto nulla di simile prima, quindi sono qui per documentarlo e chiedere aiuto!Segfaults eseguibili semplici all'avvio durante il collegamento di pthreads
miei segfaults eseguibili prima principale si chiama
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ??()
(gdb) bt
#0 0x0000000000000000 in ??()
#1 0x00007ffff7b47901 in ??() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2 0x00007ffff7b47943 in std::locale::locale()() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3 0x00007ffff7b44724 in std::ios_base::Init::Init()() from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4 0x0000000000400c1c in __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535)
at /usr/include/c++/4.8/iostream:74
#5 0x0000000000400c45 in _GLOBAL__sub_I__ZN9CrashTestC2Ev() at crash_test.cc:8
#6 0x0000000000400c9d in __libc_csu_init()
#7 0x00007ffff7512e55 in __libc_start_main (main=0x400bea <main()>, argc=1, argv=0x7fffffffdca8,
init=0x400c50 <__libc_csu_init>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffdc98)
at libc-start.c:246
#8 0x0000000000400ad9 in _start()
(gdb)
L'incidente risultante sembra simile a this question che porta a this bug report, ma il mio codice è diverso e molto sensibile ai cambiamenti. Ho ristretto il problema a 5 requisiti:
- Avere una classe implementata in una libreria condivisa.
- Dichiarare un'istanza di quella classe in un'altra, subito dopo una dichiarazione membro std :: string.
- Includere iostream
- Collegamento con pthreads
- Usa g ++ - 4.8 (o 4.9) ed il gold linker
Questo è tutto. Modifica o ometti qualsiasi requisito e il segfault non si verifica.
Ho creato un caso di test minimo. Ecco l'header eseguibile
// crash_test.h
#pragma once
#include <string>
#include "crash.h"
class CrashTest {
CrashTest(); // must have a constructor
std::string first_; // must be a string declared before Crash object
Crash crash_; // must be a value, not pointer
};
E la funzione principale è vuota. Non costruisco nemmeno la classe che ho definito! Classe
#include "crash_test.h"
#include <iostream> // required
CrashTest::CrashTest() { } // must be here, not header
int main() {
return 0;
}
The Crash non può essere più semplice
// crash.h
#pragma once
struct Crash {
Crash();
};
ma richiede un'implementazione per creare una libreria condivisa.
#include "crash.h"
Crash::Crash() {} // must be here, not header
Ho anche provato questo in un contenitore Docker su una nuova installazione di Ubuntu 14.04, con g ++ - 4.8 installato tramite apt-get.
Ecco lo script di compilazione.
#! /bin/sh
COMPILE="/usr/bin/x86_64-linux-gnu-g++-4.8 -Wall -Wextra -Wno-sign-compare -Wno-unused-parameter -Wno-missing-field-initializers -Werror -std=c++11 -O0 -g "
# Segfault only occurs using the gold linker.
LINKER="-fuse-ld=gold"
# Compile a shared library and then an executable.
# If the latter is linked with pthread, it segfaults when run.
# If the shared library is removed, there is no segfault.
$COMPILE -fPIC -o crash.o -c crash.cc \
&& $COMPILE -o crash_test.o -c crash_test.cc \
&& $COMPILE -fPIC $LINKER -shared -Wl,-soname,libcrash.so -o libcrash.so crash.o -Wl,-rpath=. \
&& $COMPILE $LINKER crash_test.o -o crash_test -rdynamic libcrash.so -pthread -Wl,-rpath=. \
&& echo "Compiled and linked..." \
&& ./crash_test \
&& echo "Did not crash!"
ho messo tutto il codice in un repo github: crash_test
Consigli apprezzato!
Come si costruisce l'applicazione? Quali comandi e quali argomenti? Usi un makefile? Come sembra? –
domanda aggiornata per includere lo script di compilazione, ma è anche nel repository che ho collegato – matt
Non si * compilano * con l'argomento '-pthread', solo collegamento. Hai provato ad aggiungere l'argomento flag '-pthread' anche durante la compilazione? –