标签: longjmp

Jmp_buf结构中的每个条目都有什么作用?

我正在运行Ubuntu 9.10(Karmic Koala),我看了一下jmp_buf结构,它只是一个12个整数的数组.当我使用setjmp并传入jmp_buf结构时,12个条目中的4个被保存.这4个条目是堆栈指针,帧指针,程序计数器和返回地址.其他8个条目是什么?它们是机器相关的吗?段表基址寄存器的另一个条目是?还有什么需要正确恢复线程/进程的环境?我查看了手册页,其他来源,但我找不到汇编代码setjmp.

c callstack longjmp

12
推荐指数
2
解决办法
8789
查看次数

如何(计算)C++中的goto和longjmp?

我通常不会编写C++代码,但我的一个奇怪的comp sci朋友厌倦了查看我精彩的FORTRAN程序并挑战我用C++重写其中一个,因为他更喜欢我的C++代码.(我们在这里投入资金.)确切的术语是它需要在现代C++编译器中进行编译.也许他讨厌一个好的conio.h - 我不知道.

现在我意识到在C++中有很好的写作方式,但是我想通过尽可能使我的C++版本成为FORTRAN-esque来获得个人胜利.对于奖励积分,当我转换代码时,这可能会节省一些时间和精力.

所以!这带我进入以下相关查询:

在gotos:

  1. 你是如何工作的?
  2. 对C++中的gotos有什么限制?
  3. 有关范围的任何担忧?(我将尽可能地尝试全局范围,但你永远不会知道.)
  4. 如果我使用GCC扩展转到void指针数组,是否有任何关于未定义行为的新问题等?


在longjmp上:

  1. 你如何安全地使用longjmp?
  2. C++中对longjmps的约束是什么?
  3. 它的作用范围是什么?
  4. 有什么特别的时刻,看起来longjmp应该是安全的,但实际上并不是我应该注意的吗?
  5. 如何使用longjmp模拟计算的goto?
  6. 如果我的程序中只有一个函数,那么使用longjmp over goto有什么明显的好处吗?

现在我的主要关注点是为此计算goto.看起来我可能会使用longjmp来完成这项工作,因为void指针数组不是C++标准的一部分,而是GCC特定的扩展.

c++ goto longjmp language-extension setjmp

12
推荐指数
2
解决办法
2915
查看次数

在调用va_end之前,longjmp可以吗?

在此问答中,您应该始终致电va_end():

va_end究竟是什么?是否总是需要打电话给它?

但是如果你到达va_end之前有一段代码longjmp呢?va_end的部分是否有任何承诺可以接受?或者从概念上讲(例如)va_start()可能会泄漏内存分配,而不仅仅是使用堆栈技巧?

c variadic-functions c89 language-lawyer longjmp

11
推荐指数
1
解决办法
234
查看次数

我可以撤消或删除atexit命令吗?

如果我放在atexit( fn );退出堆栈上,它将在程序退出时执行:从main()或从中返回exit().

我可以从堆栈中删除它吗?

你问我为什么要这样做?

我正在尝试使用简单的try-catch机制atexit,setjmplongjmp.如果可以的undo-atexit(fn);话,这将是完美的- 即使它只适用于最后注册的功能.

编辑:

在monoceres建议我自己的堆栈...

堆栈现在仅适用于一个异常捕获器.

void (*_catchFn[10])()  = {0,0,0,0,0,0,0,0,0,0};

void _catch(){
  if ( _catchFn[0] != 0 ){
    (_catchFn[0])();
  }
}

void _addCatch( void (*fn)() ){
  _catchFn[0]=fn;
}

void _remCatch( void (*fn)() ){
  _catchFn[0]=0;
}

void test(){
  jmp_buf env;

  void catch(){                  // we get here after an exit with a registered catch
    longjmp(env,1);              // return to the line marked except...
                               //   that …
Run Code Online (Sandbox Code Playgroud)

c exit atexit longjmp

10
推荐指数
2
解决办法
3905
查看次数

longjmp和RAII

所以我有一个库(不是我写的),不幸的是它abort()用来处理某些错误.在应用程序级别,这些错误是可恢复的,所以我想处理它们而不是用户看到崩溃.所以我最终编写这样的代码:

static jmp_buf abort_buffer;
static void abort_handler(int) {
    longjmp(abort_buffer, 1); // perhaps siglongjmp if available..
}

int function(int x, int y) {

    struct sigaction new_sa;
    struct sigaction old_sa;

    sigemptyset(&new_sa.sa_mask);
    new_sa.sa_handler = abort_handler;
    sigaction(SIGABRT, &new_sa, &old_sa);

    if(setjmp(abort_buffer)) {
        sigaction(SIGABRT, &old_sa, 0);
        return -1
    }

    // attempt to do some work here
    int result = f(x, y); // may call abort!

    sigaction(SIGABRT, &old_sa, 0);
    return result;
}
Run Code Online (Sandbox Code Playgroud)

代码不是很优雅.由于这种模式最终必须在代码的几个点重复,我想简化一点,并可能将它包装在一个可重用的对象中.我的第一次尝试涉及使用RAII来处理信号处理程序的设置/拆除(需要完成,因为每个函数需要不同的错误处理).所以我想出了这个:

template <int N>
struct signal_guard {
    signal_guard(void (*f)(int)) {
        sigemptyset(&new_sa.sa_mask);
        new_sa.sa_handler = …
Run Code Online (Sandbox Code Playgroud)

c++ raii signal-handling longjmp

10
推荐指数
1
解决办法
843
查看次数

究竟什么"程序状态"setjmp保存?

我已经读过传入的jmp_buf变量中的setjmp"保存程序状态",但是我还没有找到任何关于它究竟是什么的描述.它是否复制了所有应用程序的内存?只是寄存器?堆栈?

c longjmp setjmp

9
推荐指数
2
解决办法
1547
查看次数

使用setjmp在C++对象上警告"可能会被破坏"

#include <setjmp.h>
#include <vector>

int main(int argc, char**) {
 std::vector<int> foo(argc);
 jmp_buf env;
 if (setjmp(env)) return 1;
}

用GCC 4.4.1编译上面的代码,g ++ test.cc -Wextra -O1,给出了这个令人困惑的警告:

/usr/include/c++/4.4/bits/stl_vector.h: In function ‘int main(int, char**)’:
/usr/include/c++/4.4/bits/stl_vector.h:1035: warning: variable ‘__first’ might be clobbered by ‘longjmp’ or ‘vfork’

stl_vector.h的第1035行是在构造foo时调用的vector(n,value)构造函数使用的辅助函数中.如果编译器可以找出参数值(例如它是一个数字文字),警告就会消失,所以我在这个测试用例中使用了argc,因为编译器无法确定它的值.

我猜这个警告可能是因为编译器优化了向量构造,所以它实际上发生在setjmp着陆点之后(当构造函数参数依赖于函数的参数时,这似乎就是这种情况).

我怎样才能避免这个问题,最好不必将setjmp部分分解为另一个函数?

不使用setjmp不是一个选项,因为我遇到了一堆需要使用它来进行错误处理的C库.

c++ longjmp

8
推荐指数
2
解决办法
7296
查看次数

Lua coroutines - setjmp longjmp clobbering?

在不久前的博客文章中,Scott Vokes描述了与lua使用C函数实现协程相关的技术问题,setjmp并且longjmp:

Lua协同程序的主要限制是,由于它们是用setjmp(3)和longjmp(3)实现的,所以你不能用它们从Lua调用C代码调用回调用回调用C的Lua,因为嵌套的longjmp将破坏C函数的堆栈帧.(这是在运行时检测到的,而不是静默失败.)

我没有发现这在实践中是一个问题,我不知道有什么方法可以修复它而不损坏Lua的可移植性,这是我最喜欢的Lua之一 - 它几乎可以运行任何ANSI C编译器和适度的空间.使用Lua意味着我可以轻装上阵.:)

我已经使用了很多协同程序,我认为我已经广泛地理解了发生了什么setjmp,longjmp做了什么和做了什么,但是我在某个时候读到了它,并意识到我并没有真正理解它.为了弄明白这一点,我尝试制作一个我认为应该根据描述引起问题的程序,相反它似乎工作正常.

然而,我看到其他一些地方人们似乎声称存在问题:

问题是:

  • 在什么情况下,由于C函数堆栈框架遭到破坏,lua协同程序无法工作?
  • 到底是什么结果?"在运行时检测到"是否意味着,lua恐慌?或者是其他东西?
  • 这是否仍会影响lua(5.3)的最新版本,或者这实际上是5.1问题还是什么?

这是我制作的代码.在我的测试中,它与lua 5.3.1链接,编译为C代码,测试本身在C++ 11标准下编译为C++代码.

extern "C" {
#include <lauxlib.h>
#include <lua.h>
}

#include <cassert>
#include <iostream>

#define CODE(C) \
case C: { \
  std::cout << "When returning to " << where << " got code '" #C "'" << std::endl; \
  break; \
}

void handle_resume_code(int code, const char * where) {
  switch (code) {
    CODE(LUA_OK) …
Run Code Online (Sandbox Code Playgroud)

c c++ lua coroutine longjmp

8
推荐指数
1
解决办法
1286
查看次数

优秀的setjmp/longjmp教程

嗨,我想在C中阅读关于setjmp/longjmp的好教程.如果有一些真实而非人为的例子会更好.

谢谢.

c longjmp setjmp

7
推荐指数
1
解决办法
4698
查看次数

为什么setjmp(3)不能保存AMD64上的所有寄存器?

我正在浏览各种setjmplongjmp实现的来源,并注意到并非所有的CPU寄存器都保存在jmp_buf结构中.在查看AMD64 ABI之后,我注意到只保存了被调用者保存的寄存器.

我不明白当只保存了一些寄存器时,如何完全恢复功能状态.当然,未保存的寄存器必须反复多次破坏,直到我longjmp稍后再打电话为止?

然而,一切都很完美,所以肯定有一些我不明白的东西.我希望有人可以对此有所了解.

谢谢!

x86-64 longjmp

7
推荐指数
1
解决办法
694
查看次数