以下是普渡大学 CS 课上给出的示例代码。出于调试目的,我对原来的改动很少。您可以在https://www.cs.purdue.edu/homes/cs240/lectures/Lecture-19.pdf查看原始代码。我面临的问题在代码段下方进行了描述。
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <string.h>
int a(char* str, jmp_buf aenv) {
int i;
i = setjmp(aenv);
// i ++; i--;
printf("In func a: str = %s, i=%d\n", str, i); #crash causing printf
return i;
}
int b(int j, jmp_buf benv) {
printf("In func b: j= %d\n",j);
longjmp(benv, j); # segfault crash happens here, only if printf is present
}
int main(int argc, char** argv) {
jmp_buf main_env;
char *arr;
arr = (char*) malloc(100);
strcpy(arr, "As if called From main");
if ( a(arr, main_env)) {
printf("In main: a() returned non-zero\n");
exit(EXIT_SUCCESS);
}
b(3, main_env);
int i=1;
i++;
printf("In main: end \n");
return (EXIT_SUCCESS);
}
该平台是 Windows XP 中的 Netbeans IDE 7.3 和 cygwin 1.7(最新)。当我运行这个程序时,输出是
In func a: str = As if called From main, i=0
In func b: j= 3
当我单步调试调试器时,我在调用 longjmp() 时看到崩溃。程序运行,但在调试器中出现意外行为,如果我删除函数 a() 中的 printf。如果我删除 printf 并运行程序,则没有崩溃并且输出为
In func b: j=
In main: end
我已经阅读了网上关于 setjmp/longjmp 的几篇文档,我是一名专业人士。我的期望是调用 longjmp() 会将程序状态和执行带到另一个函数中的 setjmp。此函数 a() 应将 3 返回给 main。因此,main() 中的 if 条件为 TRUE,我应该看到打印输出“在 main:a() 返回非零”。根据我对 setjmp/longjmp 的理解,我没想到会打印出“In main: end”,因为控制永远不会到达那里。
我怀疑这可能是调试器问题,因为当我单步执行程序时(函数 a() 中没有 printf),调试器以预期的方式达到 longjmp。执行 longjmp 时,调试器不会在任何地方停止 - 它只是打印“In main: end”然后程序终止。我在 main() 中引入了 i++,以查看调试器是否会在打印之前停止。但是 Netbeans 并没有止步于此,整个程序在进入 longjmp() 时快速完成。
这种行为的原因是什么?在第一种情况下(当 printf 出现在函数 a() 中时)段错误的原因是什么?堆栈是否以指针“str”混乱的方式展开?为什么 ?如果有人可以访问 UNIX 机器,我想查看该系统和程序行为的输出。感谢您的意见。