2013-11-29 3 views
3

Следующий код только заканчивает печать «5»Почему программа setjmp печатает 5?

#include <iostream> 
#include <setjmp.h> 

static jmp_buf buf; 

float funcB() 
{ 
    setjmp(buf); 
    return 1.6f; 
} 

int funcA() 
{ 
    longjmp(buf,5); 
    std::cout<<"b"; 
    return 2; 
} 

int main() 
{ 
    funcB(); 
    std::cout<<funcA(); 
} 

Но это не имеет никакого смысла, так как setjmp возвращает 5, а не как функция ... Не волнуйся, я не используя этот код в любом месте, мне просто интересно!

+0

Примечание: использование setjmp/longjmp в C++ просто неверно. У нас есть бросок и улов. –

+0

Согласен, мне просто любопытно, как сильно они заворачивают вещи вверх – foips

+0

@foips Они (почти всегда) вызывают неопределенное поведение, которое так же прикручено, как вы можете получить. –

ответ

3

То, что вы пытаетесь сделать, это специально обозначается как непредсказуемое поведение в documentation:

longjmp() функция восстанавливает окружение сохраненное при последнем вызове setjmp() в том же потоке, с соответствующим jmp_buf аргументом , Если такого вызова нет или , если функция, содержащая вызов setjmp(), завершила выполнение промежуточный, поведение не определено.

Так как функция, которая называется setjmp (т.е. funcB) завершился перед вызовом longjmp в funcA, поведение не определено (it crashes on ideone).

+0

Ах, ладно, я понял. Но все же, 5 получается из параметра longjmp value и изменяется с этим значением. Было бы интересно узнать, почему это происходит с точки зрения сборки программы. – foips

+0

Также следует отметить, что я компилирую ее в clang – foips

+0

@foips. Один из способов, почему это может произойти, - это то, что компилятор возвращает значения через назначенный регистр. Поскольку 'funcB' возвращает' float', загрузка '1.6f' в регистр для возврата не изменяет значение в регистре, которое используется для возвращения целочисленных результатов.Вот почему '5' остается в регистре возврата в то время, когда' funcA' (некорректно) возвращается после путаного 'longjmp'. Изменение уровня оптимизации или возврат 'funcB' целого числа может изменить наблюдаемое неопределенное поведение. – dasblinkenlight

1

Вы не можете использовать longjmp для возврата к функции, которую вы вышли. Другими словами longjmp не будет восстанавливать стек для вас. См. here.

Что вам нужно, это язык, подобный схеме, где выполнение такого рода вещей будет абсолютно нормальным.

+0

код компилируется и запускается, в чем ваш смысл? (ах, с вашим редактированием я вижу, что вы говорите) – foips

+0

@foips Что вы используете setjmp/longjmp незаконным способом, и поэтому ваша программа имеет * неопределенное поведение *. Как будто вы разыменовали указатель NULL или что-то еще. – john

0

Оказывается, все, что компилятор вы используете, используя строгую интерпретацию того, что setjmp и longjmp сделать:

Этот макрос может вернуть более одного раза: в первый раз, на его прямой вызова; В этом случае он всегда возвращает ноль. Когда longjmp - , вызываемый с информацией, установленной в env, макрос возвращается снова; это значение возвращает значение, переданное longjmp в качестве второго аргумента, если этот отличается от нуля, или 1, если он равен нулю.

От here

Как это UB, он может сделать это, заказать пиццу, конец мира ... все было бы справедливо.

Смежные вопросы