Ответ 1
Интерпретация 1 верна. Если интерпретация 2 была предназначена, исходный текст использовал бы " или, которые были изменены" вместо "и".
Мои вопросы направлены на поведение setjmp/longjmp относительно локальных переменных.
Пример кода:
jmp_buf env;
void abc()
{
int error;
...
if(error)
longjmp(env);
}
void xyz() {
int v1; // non-volatile; changed between setjmp and longjmp
int v2; // non-volatile; not changed between setjmp and longjmp
volatile int v3; // volatile; changed between setjmp and longjmp
volatile int v4; // volatile; not changed between setjmp and longjmp
...
if(setjmp(env)) {
// error handling
...
return;
}
v1++; // change v1
v3++; // change v3
abc();
}
int main(...) {
xyz();
}
Документация setjmp/longjmp гласит:
"Все доступные объекты имеют значения с момента вызова longjmp() за исключением того, что значения объектов времени автоматического хранения, которые являются локальными для функции, содержащей вызов соответствующего setjmp(), которые не имеют изменчивого типа и которые изменены между вызовом setjmp() и longjmp() являются неопределенными. "
Я вижу следующие две возможные интерпретации:
intepretation1:
Локальные переменные восстанавливаются, кроме тех, которые являются
intepretation2:
Локальные переменные восстанавливаются, кроме
Согласно интерпретации1 после longjmp только v1 undefined. v2, v3, v4. Согласно интерпретации2 после longjmp определяется только v4. v1, v2, v3 undefined.
Какой из них прав?
BTW: Мне нужен общий ( "переносимый" ) ответ, который действителен для всех компиляторов, т.е. попытка с одним конкретным компилятором не помогает.
Интерпретация 1 верна. Если интерпретация 2 была предназначена, исходный текст использовал бы " или, которые были изменены" вместо "и".
setjmp/longjmp реализуется путем сохранения регистров (включая указатели стека и кода и т.д.) при первом прохождении и восстановления их при прыжках.
В реестрах, а не в стеке, сохраняются автоматические (так называемые локальные, стековые) переменные, которые не являются "изменчивыми" могут.
В этих обстоятельствах longjmp восстановит эти переменные регистров до их значения в момент, когда сначала был вызван setjmp().
Кроме того, особенно умный компилятор может избегать переменных, которые могут быть выведены из состояния другой переменной и вычислять их по требованию.
Однако, если переменная является автоматической, но не назначена регистром, она может быть изменена кодом между setjmp и longjmp..
Volatile явно сообщает компилятору, чтобы он не хранил переменную в регистре.
Поэтому, если вы явно не говорите, что переменная является volatile, если вы изменили переменную между setjmp/longjmp, ее значение будет зависеть от выбора, который делает компилятор, и поэтому вам не следует полагаться ( "undefined" ).