Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用setjmp longjmp时的分段错误_C++_Signals_Setjmp - Fatal编程技术网

C++ 使用setjmp longjmp时的分段错误

C++ 使用setjmp longjmp时的分段错误,c++,signals,setjmp,C++,Signals,Setjmp,我有一个学校项目,它是关于使用setjmp和longjmp进行不精确的计算。该程序启动一个计时器,该计时器将向信号处理程序发送信号 在计时器过期之前,会进行一些迭代计算(为了演示,只是一个循环没有做任何有用的事情)。在这个循环的开头有一个setjmp调用,在信号处理程序中有一个longjmp调用。这基本上迫使循环停止中间计算,并在调用longjmp的位置运行信号处理程序 我遇到的问题是,每当计算部分很短时,我似乎都会相当一致地执行segfault,但是当计算部分很长时(内部循环有许多次迭代),它

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

在计时器过期之前,会进行一些迭代计算(为了演示,只是一个循环没有做任何有用的事情)。在这个循环的开头有一个setjmp调用,在信号处理程序中有一个longjmp调用。这基本上迫使循环停止中间计算,并在调用longjmp的位置运行信号处理程序

我遇到的问题是,每当计算部分很短时,我似乎都会相当一致地执行segfault,但是当计算部分很长时(内部循环有许多次迭代),它运行得很好(还没有遇到segfault)。很明显,segfault肯定发生在计算部分周围的区域,但我无法确定它来自何处,因为调试改变了事情,就像使用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
,因此跳转目标最好是有效的。这意味着,首先调用
setjmp
,然后调用
sigaction
setitimer
您的信号处理程序将调用
longjmp
,因此跳转目标最好是有效的。这意味着,首先调用
setjmp
,然后调用
sigaction
setitimer
,您不能使用“longjmp”退出计时器之类的异步事件。它仅设计用于保存和恢复由正常调用约定保存的寄存器和堆栈指针

旁注:考虑在本地变量上使用<代码> Value关键字,如7.132.1:

中指定的 所有可访问对象都有值, 以及系统的所有其他组件 抽象机器具有状态,如 调用
longjmp
函数的时间 调用,但 自动存储期限的对象 是函数的本地属性 包含对 对应的
setjmp
宏 具有挥发性-合格类型,并具有 在
setjmp
调用和
longjmp
调用 不确定


您不能使用“longjmp”退出计时器之类的异步事件。它仅设计用于保存和恢复由正常调用约定保存的寄存器和堆栈指针

旁注:考虑在本地变量上使用<代码> Value关键字,如7.132.1:

中指定的 所有可访问对象都有值, 以及系统的所有其他组件 抽象机器具有状态,如 调用
longjmp
函数的时间 调用,但 自动存储期限的对象 是函数的本地属性 包含对 对应的
setjmp
宏 具有挥发性-合格类型,并具有 在
setjmp
调用和
longjmp
调用 不确定


使用调试器查找故障的位置如何?重要变量的值是什么?我使用的是netbeans,它使用的是gdb调试器。无论何时我在调试模式下运行,它都不会出现故障,也不知道为什么。在运行模式下只有SEGFULTS。我认为您的大括号不匹配。请固定大括号和缩进。
newmask
oldsmask
似乎已切换。在应该禁用信号时启用信号,或者看起来是这样。使用调试器查找故障的位置如何?重要变量的值是什么?我使用的是netbeans,它使用的是gdb调试器。无论何时我在调试模式下运行,它都不会出现故障,也不知道为什么。在运行模式下只有SEGFULTS。我认为您的大括号不匹配。请固定大括号和缩进。
newmask
oldsmask
似乎已切换。在应该禁用的时候启用信号,或者看起来是这样。同意,但计时器设置为1秒,因此setjmp肯定会首先运行=p。我应该按照你说的来编辑它,thx。@user623879:当调用
longjmp
时,如果
setjmp
正在(再次)运行会发生什么?您需要防止这种情况,在设置信号之前调用
setjmp
(然后在信号未屏蔽时不调用它)是最可靠的方法。我尝试了您所说的方法。代码已在上面更新。基本上,我确保信号句柄永远不会通过使用setitimer手动重置计时器来中断setjmp。我仍然得到segfault虽然…仍然没有segfault在调试模式虽然…令人困惑。我现在似乎有时会遇到这样的错误:ld.so:dl lookup.c:725:_dl_lookup_symbol_x:Assertion`version==((void*)0)|(flags&~(dl_lookup_ADD_DEPENDENCY | dl_lookup_GSCOPE_LOCK))==0'失败!同意,但计时器设置为1秒,因此setjmp肯定会运行first=p。我应该按照你说的来编辑它,thx。@user623879:当调用
longjmp
时,如果
setjmp
正在(再次)运行会发生什么?您需要防止这种情况,在设置信号之前调用
setjmp
(然后在信号未屏蔽时不调用它)是最可靠的方法。我尝试了您所说的方法。代码已在上面更新。基本上,我确保信号句柄永远不会通过使用setitimer手动重置计时器来中断setjmp。我仍然得到segfault虽然…仍然没有segfault在调试模式虽然…令人困惑。我现在似乎有时会遇到这样的错误:ld.so:dl lookup.c:725:_dl_lookup_symbol_x:Assertion`version==((void*)0)|(flags&~(dl_lookup_ADD_DEPENDENCY | dl_lookup_GSCOPE_LOCK))==0'失败!
 [121395.233842] cppapplication_[17397]: 
segfault at 2 ip b74656f6 sp bfbb5abc 
error 6 in libc-2.12.1.so[b743b000+157000