9

ho la seguente struttura:Segmentation fault durante l'accesso alla struttura-funzione statica tramite puntatore restituito

struct sys_config_s 
{ 
    char server_addr[256]; 
    char listen_port[100]; 
    char server_port[100]; 
    char logfile[PATH_MAX]; 
    char pidfile[PATH_MAX]; 
    char libfile[PATH_MAX]; 
    int debug_flag; 
    unsigned long connect_delay; 
}; 
typedef struct sys_config_s sys_config_t; 

Ho anche una funzione definita in una libreria statica (chiamiamolo A.lib):

sys_config_t* sys_get_config(void) 
{ 
    static sys_config_t config; 
    return &config; 
} 

Quindi ho un programma (chiamiamolo B) e una libreria dinamica (chiamiamola C). Sia B che C collegano con A.lib. Al runtime B apre C tramite dlopen() e quindi ottiene un indirizzo alla funzione di C func() tramite una chiamata a dlsym().

void func(void) 
{ 
    sys_get_config()->connect_delay = 1000; 
} 

Il codice sopra è il corpo della funzione di C func() e produce un errore di segmentazione quando raggiunta. Il segfault si verifica solo durante l'esecuzione all'esterno di gdb.

Perché succede?

MODIFICA: rendere sys_config_t config una variabile globale non aiuta.

risposta

1

La soluzione è banale. In qualche modo, con una mancata corrispondenza dell'intestazione, la costante PATH_MAX è stata definita in modo diverso nelle unità di compilazione di B e C. Devo essere più attento in futuro. (facepalms)

0

Non vi è alcuna differenza tra la variabile che è una variabile statico locale o una variabile statica globale. Una variabile statica è STATIC, ovvero, non è, sulla richiesta di chiamata di funzione, allocata nello stack all'interno del frame di funzione corrente, ma viene allocata in uno dei segmenti preesistenti della memoria definita nelle intestazioni binarie dell'eseguibile.

Questo è quello che sono sicuro al 100%. La domanda, dove in quale segmento sono posizionati esattamente e se sono condivisi correttamente, è un altro problema. Ho riscontrato problemi simili con la condivisione di variabili globali/statiche tra moduli, ma in genere il nucleo del problema era molto specifico per l'esatta configurazione.

Si prega di prendere in considerazione, che il codice di esempio è piccolo, e io ha lavorato su quelle piattaforme molto tempo fa. Quello che ho scritto sopra potrebbe essere errato o addirittura essere chiaramente sbagliato in alcuni punti!

Penso che l'importante sia che si ottenga quel segfault in C quando si tocca quella linea. L'impostazione di un campo intero su una costante non può aver avuto esito negativo, mai, a condizione che l'indirizzo di destinazione sia valido e non protetto da scrittura. Ciò lascia due opzioni: - la tua funzione sys_get_config() si è bloccata - o ha restituito un puntatore non valido.

Dato che si dice che il segfault viene generato qui, non in sys_get_config, l'unica cosa rimasta è l'ultimo punto: puntatore spezzato.

Aggiungi al sys_get_config qualche printf banale che eseguirà il dump dell'indirizzo da restituire, quindi eseguirà la stessa funzione di chiamata "func". Controlla se non è nullo, e controlla anche se entro sys_get_config è lo stesso di dopo essere stato restituito, solo per essere sicuro che le convenzioni di chiamata siano corrette, ecc. Una buona idea per fare un doppio/triplo controllo è anche aggiungere all'interno modulo "A" una copia della funzione sys_get_config (con nome diverso ovviamente), e per verificare se gli indirizzi restituiti da sys_get_config e la sua copia sono gli stessi. Se non lo sono, qualcosa è andato storto durante il collegamento

C'è anche una possibilità molto piccola che il caricamento del modulo sia stato rinviato e si sta tentando di fare riferimento a una memoria di un modulo che non è stato ancora completamente inizializzato. Ho lavorato su Linux molto tempo fa, ma ricordo che dlopen ha varie opzioni di caricamento. Ma hai scritto che hai ricevuto l'indirizzo da dlsym, quindi suppongo che il modulo abbia caricato dal momento che hai l'indirizzo finale del simbolo.

Problemi correlati