gpt4 book ai didi

c++ - 使用 setjmp longjmp 时出现段错误

转载 作者:太空宇宙 更新时间:2023-11-04 12:20:14 24 4
gpt4 key购买 nike

我有这个学校项目,它是关于使用 setjmp 和 longjmp 进行不精确计算的。该程序启动一个计时器,该计时器将向信号处理程序发出信号。

在计时器到期之前,有一些迭代计算(出于演示目的,只是一个没有任何用处的循环)。在此循环的开头有一个 setjmp 调用,在信号处理程序中有一个 longjmp 调用。这基本上会强制循环停止中间计算并在它调用 longjmp 的地方运行信号处理程序。

我遇到的问题是,每当计算部分很短时,我似乎相当一致地出现段错误,但是当计算部分很长时(内部循环有很多迭代),它运行得很好(没有遇到段错误)。显然,段错误一定发生在该计算部分周围的区域,但我无法弄清楚它是从哪里来的,因为调试会像使用 print 语句一样改变事物。

这是我的代码:

#include <iostream>
#include <signal.h>
#include <sys/time.h>
#include <setjmp.h>
#include <errno.h>
#include <stdlib.h>

jmp_buf env;


static void usr_timer_tick(int signal)
{
if(signal == SIGALRM)
{
longjmp(env, 1);
}
}


/*Program Description
* This program first sets up the timer to signal usr_timer_tick
* every 1 second on the SIGALRM signal. It then proceeds to do an iterated calculation three times.
* An infinite loop calls setjmp and when 0 is returned, continues doing
* a calculation on temp. After an iteration is complete, the result of
* the iteration is saved into finalResult after blocking SIGALRM to
* make the saving of the result atomic.
*
* Once the signal handler(usr_timer_tick) is triggered, it calls longjmp which forces
* setjmp to return a non-zero value, which causes the main function to break out
* of the infinite loop and start a new calculation...this is done a total of 3
* times for demonstration purposes.
*/
int main(int argc, char **argv)
{

//init timer using setitimer..real mode
int which = ITIMER_REAL;
struct itimerval value;
struct sigaction sact;
sigset_t newmask, oldmask;
sigemptyset( &newmask );
sigemptyset( &oldmask );
sigaddset(&newmask, SIGALRM);

sact.sa_flags = 0;
sact.sa_handler = usr_timer_tick;
sigaction( SIGALRM, &sact, NULL );
// value.it_interval.tv_sec = 0; /* One second */
// value.it_interval.tv_usec = 0;
// value.it_value.tv_sec = 1; /* One second */
// value.it_value.tv_usec = 0;
//
// setitimer(which, &value, NULL);



double finalResult = 0;
int loopcount = 0;
double tempResult = 0;
for(int j = 0; j < 10; j++)
{
loopcount = 0;


std::cout << "Run " << j << " begin loop "
<< loopcount << "\n";


if(setjmp(env) == 0)
{ //timer not hit yet

//sigprocmask(SIG_BLOCK, &newmask, NULL);
value.it_interval.tv_sec = 0; /* One second */
value.it_interval.tv_usec = 0;
value.it_value.tv_sec = 1; /* One second */
value.it_value.tv_usec = 0;

setitimer(which, &value, NULL);

//sigprocmask(SIG_SETMASK, &oldmask, NULL);
for(;;)
{
//Do some random calculations
for(int i = 0; i < 1; i++)
{
tempResult = tempResult + .001;
}

//block signal from arriving and save to finalResult
if(sigprocmask(SIG_BLOCK, &newmask, NULL) < 0) exit(-1);
finalResult = tempResult;
std::cout << "Run " << j << " complete loop "
<< loopcount << " result = " << finalResult<< "\n";
loopcount++;
if(sigprocmask(SIG_SETMASK, &oldmask, NULL)< 0) exit(errno);
}
}
else
{
//timer signal arrived, print the final result and get out of loop
std::cout << "***Run " << j << " killed on loop "
<< loopcount << " result = "<< finalResult << "\n";
sigprocmask(SIG_SETMASK, &oldmask, NULL);
//break;
}



}
return 0;
}

我知道你们中的一些人可能不同意在信号处理程序中使用 longjmp,但这是我的教授所说的那样做。另外,应该注意的是,我在调用 longjmp 后解除了对 SIGALRM 的阻塞(参见 main 的 else 语句)。

查看 dmesg 我得到:

 [121395.233842] cppapplication_[17397]: 
segfault at 2 ip b74656f6 sp bfbb5abc
error 6 in libc-2.12.1.so[b743b000+157000

]

最佳答案

您不能使用“longjmp”从定时器等异步事件中退出。它仅用于保存和恢复由普通调用约定保存的寄存器和堆栈指针。

旁注:考虑在局部变量上使用 volatile 关键字,如 7.13.2.1 中所指定:

All accessible objects have values, and all other components of the abstract machine have state, as of the time the longjmp function was called, except that the values of objects of automatic storage duration that are local to the function containing the invocation of the corresponding setjmp macro that do not have volatile-qualified type and have been changed between the setjmp invocation and longjmp call are indeterminate.

关于c++ - 使用 setjmp longjmp 时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5490038/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com