Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.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++ 通过sigsetjmp和longsetjmp恢复环境_C++_Context Switch - Fatal编程技术网

C++ 通过sigsetjmp和longsetjmp恢复环境

C++ 通过sigsetjmp和longsetjmp恢复环境,c++,context-switch,C++,Context Switch,我将sigsetjmp和singlongjmp与sigallarm结合使用来中断系统调用,如下代码所示 //data of Alarm_interrupter void (TClass::*fpt)(const char*); // pointer to member function TClass* pt2Object; // pointer to object ===============================================

我将sigsetjmp和singlongjmp与sigallarm结合使用来中断系统调用,如下代码所示

//data of Alarm_interrupter
void (TClass::*fpt)(const char*);   // pointer to member function
TClass* pt2Object;                  // pointer to object
===================================================
//for timeout processing
static sigjmp_buf jmpbuf;
static void recvfrom_alarm(int) {
    siglongjmp(jmpbuf, 1);
}
======================================================
void Alarm_interrupter::start_timeout() {
    signal(SIGALRM, recvfrom_alarm);
    alarm(timeout);
    (*pt2Object.*fpt)("timeouted before sigsetjmp"); //this call works OK
    if (sigsetjmp(jmpbuf,1) != 0) {
        //at this point, pt2Object is still OK,
        //but fpt seems to point to nothign.
        (*pt2Object.*fpt)("timeouted after sigsetjmp");
    }
    return;
}
==============================================================
在sigsetjmp return 1之前,使用对象和方法指针的调用:*pt2Object.*fpt(“sigsetjmp之前的timeouted”)是正常的,但在sigsetjmp return 1之后,此调用失败。 在检查变量的状态之后,我注意到对象指针“pt2Object”仍然正常,但方法指针“fpt”似乎有所不同

我认为其中一个可能的原因是sigsetjmp无法恢复整个早期环境,其中包括方法指针“fpt”


你们能帮我解决这个问题吗。非常感谢

正如Potatoswatter指出的那样,使用报警延迟
longjmp
太聪明了,不值得依赖。你必须先调用'sigsetjmp'。在你试图返回那里之前,它必须发生

sigsetjmp
setjmp
的唯一工作方式是遵循此伪代码

if (sigsetjmp(...) != 0) {
    //  Error handling code
}
// code that might call siglongjmp to bail out to Error handling code
要执行上下文的保存,必须执行一次。这将初始化
jmpbuf
。如果在执行之前没有调用
setjmp
而调用
longjmp
,则无法预测行为

另外,
longjmp
将倾向于删除您可能尝试使用的任何局部变量

int var = 3;
var = 2;
if (sigsetjmp(...) != 0) {
    //  Error handling code
    printf("%d", var); // could print 2, 3 or even "potato". Local vars get trashed.
}
// code that might call siglongjmp to bail out to Error handling code
所以在
*setjmp
之后,您真的想做所有有趣的事情

int var = 3;
if (sigsetjmp(...) != 0) {
    //  Error handling code
    var = 2;
    printf("%d", var); // now you know it's 2
}
// code that might call siglongjmp to bail out to Error handling code
要想让它在
*longjmp
中存活下来,需要将其标记为
volatile

volatile int var = 3;
var = 2;
if (sigsetjmp(...) != 0) {
    //  Error handling code
    printf("%d", var); // probably 2
}
// code that might call siglongjmp to bail out to Error handling code
即使这样也可能不够。它可能需要被称为sigu或类似的东西。但是尽量不要需要像那样疯狂的东西

int var = 3;
memcpy(var, (int *){2}); //memcpy is pretty reliable (C99ism: immediate pointer))
if (sigsetjmp(...) != 0) {
    //  Error handling code
    printf("%d", var); // probably 2
}
// code that might call siglongjmp to bail out to Error handling code

请不要使用
setjmp
等,也不要使信号处理程序复杂化。有更好的机制。请说明需要什么。这些函数不会恢复静态/全局变量的值。@EdHeal:实际上几乎所有“更好的机制”都有无法解决的竞争条件。如果您确实想使用
报警
可靠地中断一个操作(并且只有在被中断的操作是异步信号安全的情况下才合法),某种形式的
longjmp
是您唯一的选择。@R.我不同意。信号不受控制。使信号处理程序更简单。在黑板上做一个标记,然后流程可以定期检查该标记是否存在。至少流程会知道ir在其思路中的位置。@Potatoswatter-为什么有这么多双重否定-你的论点没有任何意义。是的,我确实在调用siglongjmp之前调用了sigsetjmp。超时后,调用siglongjmp为call,会触发sigsetjmp return 1,错误代码为call。但是调用“(*pt2Object.*fpt)(“sigsetjmp之后的timeouted”);”不再起作用。你能给我解释一下吗?不,你不能。一旦设置了信号处理程序,
siglongjmp
就有可能被调用,但是您还没有调用
sigsetjmp
。他指的是第二个调用,在“处理程序”中@khanhhh89您偏离了我展示的伪代码。它必须遵循这种形式。@khanhhh89 R所说的是,您依赖报警超时来延迟信号处理程序。最好在
sigsetjmp
@Potatoswatter Yes之后再设置警报。很好的说法。