Il seguente codice riassume il problema che ho al momento. Il mio attuale flusso di esecuzione è il seguente e un I è in esecuzione in GCC 4.3.SetJmp/LongJmp: Perché viene generato un segfault?
jmp_buf a_buf;
jmp_buf b_buf;
void b_helper()
{
printf("entering b_helper");
if(setjmp(b_buf) == 0)
{
printf("longjmping to a_buf");
longjmp(a_buf, 1);
}
printf("returning from b_helper");
return; //segfaults right here
}
void b()
{
b_helper();
}
void a()
{
printf("setjmping a_buf");
if(setjmp(a_buf) == 0)
{
printf("calling b");
b();
}
printf("longjmping to b_buf");
longjmp(b_buf, 1);
}
int main()
{
a();
}
Il flusso di esecuzione sopra riportato crea un segfault subito dopo il ritorno in b_helper. È quasi come se solo il frame stack b_helper fosse valido e gli stack sottostanti venissero cancellati.
Qualcuno può spiegare perché questo sta accadendo? Immagino che sia un'ottimizzazione GCC che cancella frame stack inutilizzati o qualcosa del genere.
Grazie.
C'è un modo per longjmp down the stack frame? È possibile copiare lo stack da b a b_helper nell'heap ed eseguirlo da lì? Inoltre, perché lo stack frame a cui fa riferimento b_buf non è più valido dopo aver saltato lo stack delle chiamate? – jameszhao00
Una volta che una parte della pila viene rilasciata, è completamente non valida (altre chiamate di funzione, interruzioni o qualsiasi altra cosa potrebbe sovrascrivere la memoria). –
Si può pensare a un 'longjmp()' come a un "ritorno esteso". Un riuscito 'longjmp()' funziona come una serie di ritorni successivi, svolgendo lo stack di chiamate fino a raggiungere il corrispondente 'setjmp()'. Una volta che i telegrammi di stack delle chiamate vengono svolti, non sono più validi. Ciò è in contrasto con le implementazioni di coroutine (ad esempio Modula-2) o continuazioni (ad esempio Scheme) in cui lo stack di chiamate rimane valido dopo il salto da qualche altra parte.C e C++ supportano solo un singolo stack di chiamate lineari, * a meno che * non utilizzi thread in cui crei più stack di chiamate indipendenti. –