2016-01-15 14 views
8

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:

  1. Avere una classe implementata in una libreria condivisa.
  2. Dichiarare un'istanza di quella classe in un'altra, subito dopo una dichiarazione membro std :: string.
  3. Includere iostream
  4. Collegamento con pthreads
  5. 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!

+0

Come si costruisce l'applicazione? Quali comandi e quali argomenti? Usi un makefile? Come sembra? –

+0

domanda aggiornata per includere lo script di compilazione, ma è anche nel repository che ho collegato – matt

+0

Non si * compilano * con l'argomento '-pthread', solo collegamento. Hai provato ad aggiungere l'argomento flag '-pthread' anche durante la compilazione? –

risposta

3

Sembra che tu stia correndo il problema descritto in this gold ticket. In base ai commenti a quel ticket, la seguente soluzione risolveva il problema: Modifica la riga di comando del linker per includere il parametro -Wl,--no-as-needed. Per il vostro script di build, che sarebbe:

$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=. -Wl,--no-as-needed 

Ma come ho detto, questo è solo una soluzione, e non sono sicuro se questo è una soluzione accettabile per voi. Se hai bisogno di una soluzione adeguata, dovresti probabilmente rivivere quel biglietto e pubblicare i tuoi risultati lì.

Problemi correlati