Что странного в переносе setjmp и longjmp? - PullRequest
4 голосов
/ 22 апреля 2010

Я впервые использую setjmp и longjmp и столкнулся с проблемой, возникающей при переносе setjmp и longjmp.Я свел код к следующему примеру:

#include <stdio.h>
#include <setjmp.h>

jmp_buf jb;

int mywrap_save()
{
  int i = setjmp(jb);
  return i;
}

int mywrap_call()
{
  longjmp(jb, 1);
  printf("this shouldn't appear\n");
}

void example_wrap()
{
  if (mywrap_save() == 0){
    printf("wrap: try block\n");
    mywrap_call();
  } else {
    printf("wrap: catch block\n");
  }
}

void example_non_wrap()
{
  if (setjmp(jb) == 0){
    printf("non_wrap: try block\n");
    longjmp(jb, 1);
  }  else {
    printf("non_wrap: catch block\n");
  }
}

int main()
{
  example_wrap();
  example_non_wrap();
}

Сначала я думал, что example_wrap () и example_non_wrap () будут вести себя одинаково.Однако результат запуска программы (GCC 4.4, Linux):

wrap: try block
non_wrap: try block
non_wrap: catch block

Если я отслеживаю программу в gdb, я вижу, что даже если mywrap_save () возвращает 1, ветвь else после возврата выглядит странным образом.игнорируются.Кто-нибудь может объяснить, что происходит?

Ответы [ 2 ]

10 голосов
/ 22 апреля 2010
 The longjmp() routines may not be called after the routine which called
 the setjmp() routines returns.

Другими словами, вы портите свой стек.

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

1 голос
/ 28 сентября 2012

setjmp() сохранит текущий стек вызовов и отметит точку. Когда стек вызовов растет, независимо от того, как далеко от отмеченной точки вы можете использовать longjmp(), чтобы перейти к отмеченной точке, как будто вы никогда не покидали точку.

В вашем коде при возврате из mywrap_save() отмеченная точка больше не действительна, пространство стека вокруг точки было грязным, поэтому вы не можете вернуться к грязной точке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...