- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有这个学校项目,它是关于使用 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 correspondingsetjmp
macro that do not have volatile-qualified type and have been changed between thesetjmp
invocation andlongjmp
call are indeterminate.
关于c++ - 使用 setjmp longjmp 时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5490038/
我想使用 setjmp/longjmp 在主函数中重用一些代码(注意:这只是一个练习,而不是我在现实世界中认真计划做的事情)。 以下代码是我想出的: #include #include jmp_b
根据我的理解,setjmp 保存当前上下文,它应该在调用 longjmp 时恢复它。然而,下一段代码打印出 15(我使用 -g 编译并且没有进行任何优化)。我是不是误解了这个结构,还是遗漏了其他任何东
来自问题: Is it good programming practice to use setjmp and longjmp in C? 留下的两条评论说: "You can't throw an
我正在使用以下代码尝试读取来自用户的输入,如果超过 5 秒则超时并退出。这是通过 setjmp/longjmp 和 SIGALRM 信号的组合来实现的。 代码如下: #include #includ
Michael Kerrisk 的“Linux 编程接口(interface)”中的练习 6.2 要求: Write a program to see what happens if we try t
我需要了解 longjmp 函数的工作原理;我知道它的作用,但我需要知道它是如何做到的。 我试图对 gdb 中的代码进行 disas,但我无法理解某些步骤。代码是: 0xb7ead420 :
下面的代码无法正常工作。谁能指出原因 #define STACK_SIZE 1524 static void mt_allocate_stack(struct thread_struct *mythr
这是我的代码: #include #include #include jmp_buf buf; void handler(int s); int main(int argc, char **ar
一段代码在这里 jmp_buf mark; int Sub_Func() { int be_modify, jmpret; be_modify = 0; jmp
我的问题针对的是 setjmp/longjmp 关于局部变量的行为。 示例代码: jmp_buf env; void abc() { int error; ... if(error)
我必须使用 setjmp/longjmp 实现用户级线程库作为作业。这是我写的代码: #include #include #include #include #include #includ
我正在尝试使用 longjmp 在 c 中实现控制的重新反转,目前我有以下代码: #include #include jmp_buf env; int arg; typedef void (*fp
这个问题来自 SetJmp/LongJmp: Why is this throwing a segfault? 当我使用 Debug模式运行代码时,它确实按预期崩溃了。但是如果我使用 release
#include #include #include #include static jmp_buf env_alrm; static void sig_alarm(int signo) {
所以我有一个库(不是我写的),不幸的是它使用 abort() 来处理某些错误。在应用程序级别,这些错误是可恢复的,所以我想处理它们而不是让用户看到崩溃。所以我最终写了这样的代码: static jmp
我的问题针对的是 setjmp/longjmp 关于局部变量的行为。 示例代码: jmp_buf env; void abc() { int error; ... if(error)
我正在调查setjmp/longjmp,发现setjmp 保存指令指针、堆栈指针等寄存器... 然而,我在这里没有得到的是,在调用 setjmp 和 longjmp 之间,不能修改线程本身堆栈中的数据
在 Why volatile works for setjmp/longjmp , 用户 greggo评论: Actually modern C compilers do need to know t
据我了解,setjmp()的典型用法和 longjmp()是异常处理(libpng 中的用法应该是一个著名的例子)并且最多只有一次调用 longjmp()一个 setjmp()称呼。 是否允许安全地做
有没有办法使用 setjmp 来实现多任务处理?和 longjmp职能 最佳答案 这是所谓的用户空间上下文切换的一种形式。 这是可能的,但很容易出错,特别是如果您使用 setjmp 和 longjmp
我是一名优秀的程序员,十分优秀!