2015-07-23 10 views
18

Su Ubuntu 14.04 LTS a 64 bit, sto provando a compilare un semplice programma OpenGL che usa il glut. Ricevo un errore di segmentazione (SIGSEV) prima che qualsiasi linea di codice venga eseguita in main; anche su un programma di test molto ridotto. Cosa potrebbe causare questo?Errore di segmentazione prima di main() quando si usa glut e std :: string?

La mia linea di comando:

g ++ -Wall -g main.cpp -lglut -lGL -lGLU -o principale

mio semplice caso di test:

#include <GL/gl.h>                                   
#include <GL/glu.h> 
#include <GL/glut.h> 

#include <string> 
#include <cstdio> 

int main(int argc, char** argv){ 
    printf("Started\n");                         
    std::string dummy = "hello"; 
    glutInit(&argc, argv); 
    return 0; 
} 

Quando eseguo il programma , il printf all'inizio del main non può essere eseguito prima del segfault. Sotto GDB, ho questa traccia indietro dopo la segfault è

#0 0x0000000000000000 in ??() 
#1 0x00007ffff3488291 in init() at dlerror.c:177 
#2 0x00007ffff34886d7 in _dlerror_run ([email protected]=0x7ffff3488130 <dlsym_doit>, [email protected]=0x7fffffffddf0) at dlerror.c:129 
#3 0x00007ffff3488198 in __dlsym (handle=<optimized out>, name=<optimized out>) at dlsym.c:70 
#4 0x00007ffff702628e in ??() from /usr/lib/nvidia-352/libGL.so.1 
#5 0x00007ffff6fd1aa7 in ??() from /usr/lib/nvidia-352/libGL.so.1 
#6 0x00007ffff7dea0fd in call_init (l=0x7ffff7fd39c8, [email protected]=1, [email protected]=0x7fffffffdf48, [email protected]=0x7fffffffdf58) at dl-init.c:64 
#7 0x00007ffff7dea223 in call_init (env=<optimized out>, argv=<optimized out>, argc=<optimized out>, l=<optimized out>) at dl-init.c:36 
#8 _dl_init (main_map=0x7ffff7ffe1c8, argc=1, argv=0x7fffffffdf48, env=0x7fffffffdf58) at dl-init.c:126 
#9 0x00007ffff7ddb30a in _dl_start_user() from /lib64/ld-linux-x86-64.so.2 
#10 0x0000000000000001 in ??() 
#11 0x00007fffffffe2ba in ??() 
#12 0x0000000000000000 in ??() 

Ed ecco il kicker. Se commento o o la riga gluInit o la riga fittizia std :: string, il programma viene compilato ed eseguito correttamente. Fino a quando non ho notato questo, ho pensato che ci fosse qualcosa di sbagliato nel mio GLUT (anche se ho provato il programma originale su cui sto eseguendo il debugging (che ho ridotto a questo esempio)) diversi sistemi senza successo. Sono un po 'in perdita qui.

Modifica: ho provato i suggerimenti di gmbeard. Turining off optimizations (-O0) non ha modificato nulla sul callstack prodotto da gdb.

ldd sul programma in esecuzione mi dà:

linux-vdso.so.1 => (0x00007ffe3b7f1000) 
libglut.so.3 => /usr/lib/x86_64-linux-gnu/libglut.so.3 (0x00007f04978fa000) 
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f04975f6000) 
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f04973e0000) 
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f049701b000) 
libGL.so.1 => /usr/lib/nvidia-352/libGL.so.1 (0x00007f0496cec000) 
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f04969b7000) 
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f04966b1000) 
libXi.so.6 => /usr/lib/x86_64-linux-gnu/libXi.so.6 (0x00007f04964a1000) 
libXxf86vm.so.1 => /usr/lib/x86_64-linux-gnu/libXxf86vm.so.1 (0x00007f049629b000) 
/lib64/ld-linux-x86-64.so.2 (0x00007f0497b44000) 
libnvidia-tls.so.352.21 => /usr/lib/nvidia-352/tls/libnvidia-tls.so.352.21 (0x00007f0496098000) 
libnvidia-glcore.so.352.21 => /usr/lib/nvidia-352/libnvidia-glcore.so.352.21 (0x00007f0493607000) 
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007f04933f5000) 
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f04931f1000) 
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f0492fd2000) 
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f0492dce000) 
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f0492bc8000) 

E poi, dopo aver individuato quale libGL sto usando, mi sono imbattuto su di esso LDD

linux-vdso.so.1 => (0x00007ffc55df8000) 
libnvidia-tls.so.352.21 => /usr/lib/nvidia-352/tls/libnvidia-tls.so.352.21 (0x00007faa60d83000) 
libnvidia-glcore.so.352.21 => /usr/lib/nvidia-352/libnvidia-glcore.so.352.21 (0x00007faa5e2f2000) 
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007faa5dfbd000) 
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007faa5ddab000) 
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007faa5d9e6000) 
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007faa5d7e2000) 
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007faa5d4dc000) 
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007faa5d2bd000) 
/lib64/ld-linux-x86-64.so.2 (0x00007faa612b5000) 
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007faa5d0b9000) 
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007faa5ceb3000) 

Ma una rapida occhiata non rivela qualcosa di sbagliato

+0

Penso che sia perché non passi alcun arg try prova ad aggiungere quelle linee befaure alla printf 'argc = 1; argv [0] = "test"; 'scusa non posso provarlo perché sono in treno. – Mido

+0

Nah, si rompe ancora se passo Args da riga di comando. Dal momento che si blocca prima che anche main sia in esecuzione, ciò non avrebbe comunque molto senso. – MikeMx7f

+1

Prova 'LD_DEBUG = all./Main' o' LD_DEBUG = tutto LD_DEBUG_OUTPUT = log.txt./Main'. Forse può spiegare cosa sta facendo 'ld.so' prima di andare in crash. –

risposta

18

in modo da vedere nell'output LD_DEBUG:

L'ultima cosa esso stampa è: "20863: simbolo = __ pthread_key_create; ricerca nel file =/usr/lib/x86_64-linux-gnu/libXdmcp .so.6 [0]

significa che ld.so id alla ricerca di __pthread_key_create dal momento che è necessario per uno dei vostri librarie [e è meglio trovare quello biblioteca è necessario questo simbolo, forse risponderà quale libreria ha bisogno di libpthread.so].

Quindi __pthread_key_create deve essere in libpthread.so ma non si dispone di libpthread.so nell'output ldd. Come puoi vedere sotto il tuo programma si blocca probabilmente usando __pthread_key_create in init().Dal modo in cui si può provare anche

LD_PRELOAD=/lib64/libpthread.so.0 ./main 

al fine di assicurarsi che pthread_key_create viene caricato prima di altri simboli.

Quindi è improbabile che lo lgut sia un problema. Chiama semplicemente dlsym durante l'inizializzazione ed è un comportamento assolutamente corretto. Ma il programma si blocca:

#0 0x0000000000000000 in ??() 
#1 0x00007ffff3488291 in init() at dlerror.c:177 
#2 0x00007ffff34886d7 in _dlerror_run ([email protected]=0x7ffff3488130 <dlsym_doit>, [email protected]=0x7fffffffddf0) at dlerror.c:129 

Questo backtrace dimostra che una funzione con 0x00000000 indirizzo (la mia ipotesi è ancora irrisolto indirizzo di __pthread_key_create) è stato chiamato e che è un errore. Quale funzione è stata chiamata? Guardate fonti:

Questo è dlerror.c: 129 (telaio # 2):

int 
internal_function 
_dlerror_run (void (*operate) (void *), void *args) 
{ 
    struct dl_action_result *result; 

    /* If we have not yet initialized the buffer do it now. */ 
    __libc_once (once, init); 

(telaio # 1):

/* Initialize buffers for results. */ 
static void 
init (void) 
{ 
    if (__libc_key_create (&key, free_key_mem)) 
    /* Creating the key failed. This means something really went 
     wrong. In any case use a static buffer which is better than 
     nothing. */ 
    static_buf = &last_result; 
} 

Dev'essere __libc_key_create che è una macro e ha in glibc diverse definizioni. Se si costruisce per POSIX è definita

/* Create thread-specific key. */ 
#define __libc_key_create(KEY, DESTRUCTOR) \ 
    __libc_ptf_call (__pthread_key_create, (KEY, DESTRUCTOR), 1) 

vi ho chiesto di costruire con:

g++ -pthread -Wall -g main.cpp -lpthread -lglut -lGL -lGLU -o main 

Al fine di assicurarsi che __libc_key_create infatti chiamate __pthread_key_create e lpthread viene inizializzato prima -lglut. Ma se non si desidera utilizzare -pthread poi eventualmente è necessario analizzare telaio # 1

#1 0x00007ffff3488291 in init() at dlerror.c:177 

Ad esempio è possibile aggiungere disasemble per il frame # 1 alla tua domanda

+3

Grazie mille! Mi sono appena svegliato e ho provato a risolvere i problemi in base ai tuoi suggerimenti. Ho localizzato il mio libpthread.so e ho provato "LD_PRELOAD =/lib/x86_64-linux-gnu/libpthread.so.0 ./main", che ha funzionato! Quindi l'errore è come hai suggerito; libpthread era per qualche motivo richiesto, ma non collegato, né poteva essere collegato semplicemente usando -lpthread o -pthread. – MikeMx7f

+2

ho aggiunto una seconda soluzione, che non richiede LD_PRELOAD, convincendo il compilatore/linker che ho davvero bisogno libpthread: ho aggiunto questo al mio main.cpp '#include void * simpleFunc (void *) { return NULL; } void forcePThreadLink() { pthread_t t1; pthread_create (& t1, NULL, & simpleFunc, NULL); } ' Questo è sciocco, ma funziona. Ora qual è la procedura qui: dovrei accettare questa risposta come è (dal momento che ha portato a una soluzione alternativa), e aprire una nuova domanda per perché diamine non posso collegarmi a pthread quando ne ho chiaramente bisogno fino a quando non scrivo qualche stupido hack? – MikeMx7f

+0

Non sono sicuro della procedura. Ma puoi sempre pubblicare la tua risposta e accettarla se è la migliore risposta –

0

È possibile che il programma e libGL siano collegati o utilizzando due versioni in conflitto di una terza libreria (forse libc?). È difficile da diagnosticare con i dettagli che hai fornito. È possibile disabilitare le ottimizzazioni (-O0) e vedere se GDB fornisce ulteriori indizi. Puoi vedere quali dipendenze hanno sia il tuo programma che libGL eseguendo ldd - questo mostra le dipendenze in fase di compilazione. Spiacente, posso solo dare suggerimenti: questi tipi di problemi di runtime possono verificarsi per diversi motivi.

+0

Grazie per i suggerimenti, ho provato entrambi i tuoi suggerimenti (e aggiornato il post originale con i dettagli); ma non penso di chiudermi per rompere il mistero. libc sembra essere lo stesso tra libGL e il mio programma (i percorsi sono identici sebbene gli indirizzi di memoria siano in qualche modo diversi). Altre idee? – MikeMx7f

0

ho incontrato un problema simile, ma LD_PRELOAD=/lib/x86_64-linux-gnu/libpthread.so.0 ./main non sempre ha funzionato. Questo problema si è verificato sulla GPU NVIDIA, OpenGL è collegato a /usr/lib/nvidia-352/libGL.so.1, dopo aver provato su diversi computer, trovo che la versione g ++ a g ++ - 5 funziona o il collegamento a 'mesa/libGL.so', un'altra implementazione OpenGL, per g++ main.cpp -o main -Wl, --rpath /usr/lib/x86_64-linux-gnu/mesa -lGLU -lGL -lglut.

Problemi correlati