标签: setjmp

不一致的警告:变量可能被'longjmp'或'vfork'破坏

我大多说服自己,我遇到了一些g ++ 4.8.3错误,但我想我会首先问这个列表,因为我对setjmp/longjmp的经验很少.我将我的代码简化为以下foo.cxx:

#include <setjmp.h>
#include <string.h>

// Changing MyStruct to be just a single int makes the compiler happy.
struct MyStruct
{
    int a;
    int b;
};

// Setting MyType to int makes the compiler happy.
#ifdef USE_STRUCT
typedef MyStruct MyType;
#elif USE_INT
typedef int MyType;
#endif

void SomeFunc(MyType val)
{
}

static void static_func(MyType val)
{
    SomeFunc(val);
}

int main(int argc, char **argv)
{
    jmp_buf env;
    if (setjmp(env))
    {
        return 1;
    }

    MyType val;
#ifdef USE_STRUCT
    val.a = …
Run Code Online (Sandbox Code Playgroud)

c++ longjmp setjmp g++4.8

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

链接到C++库时在C中使用setjmp和longjmp

我想在C程序中使用setjmp和longjmp,该程序链接到用C++实现的库(但有一个C API).

C++代码确实进行了动态内存分配,指针通过API传递,但只要代码的C端正确管理那些(不透明)对象,使用longjmp就不会有任何混乱,对吧?

我知道在C++代码中使用这些函数是不安全的,但它是否应该在链接到C++代码的C代码中安全?

c c++ longjmp setjmp

6
推荐指数
1
解决办法
743
查看次数

这段代码是否包含隐藏的错误?

以下代码:

  • 使用gcc版本4.4.5(Ubuntu/Linaro 4.4.4-14ubuntu5/32bits)编译时运行正常
  • 使用MSVC10(Win7/32bits)编译时运行正常
  • 使用gcc版本4.5.2(Win7/32位上的MinGW)运行时崩溃

main.cpp:

# include <iostream>
# include <csetjmp>
# include <stdexcept>

using namespace std ;

void do_work(jmp_buf context)
{
    try
    {
        throw runtime_error("Ouch !") ;
    }
    catch(exception & e)
    {
    }

    longjmp(context, -1) ;                        //BP1
}

int main(int, char *[])
{
    jmp_buf context ;

    try
    {
        if( setjmp(context) != 0 )
        {
            throw runtime_error("Oops !") ;       //BP2
        }

        do_work(context) ;
    }
    catch(exception & e)
    {
        cout << "Caught an exception saying : " << e.what() …
Run Code Online (Sandbox Code Playgroud)

c++ mingw setjmp

6
推荐指数
1
解决办法
541
查看次数

如何安全获取setjmp的返回值

我想使用 longjmp 返回错误代码,并从调用 setjmp 的函数传递它。简化代码:

int do_things(stuff ........)
{
 int error_code;
 jmp_buf jb;

 if ((error_code = setjmp(jb)) == 0) {
    /* do stuff */
    return 0;
 }
 else {
    return error_code;
 }
}
Run Code Online (Sandbox Code Playgroud)

但我读到:“setjmp 宏的调用只能出现在以下上下文之一中:”

 the entire controlling expression of a selection or iteration statement

if (setjmp(jb)) {
switch (setjmp(jb)) {
while (setjmp(jb)) {
Run Code Online (Sandbox Code Playgroud)

或者

 one operand of a relational or equality operator with the other operand
 an integer constant expression, with the resulting expression being
 the entire controlling expression …
Run Code Online (Sandbox Code Playgroud)

c setjmp

6
推荐指数
1
解决办法
1184
查看次数

安全使用“setjmp”和“longjmp”

我知道人们总是说不要使用longjmp,它是邪恶的,它是危险的。

但我认为它对于退出深度递归/嵌套函数调用很有用。

是不是一次下单longjmp比多次重复检查和退货要快一些if(returnVal != SUCCESS) return returnVal;

至于安全性,只要动态内存等资源释放得当,应该不会有问题吧?

到目前为止,使用似乎longjmp并不困难,甚至使我的代码更简洁。我很想经常使用它。

(恕我直言,在许多情况下,首先在深度递归中没有分配动态内存/资源。深度函数调用对于数据解析/操作/验证来说似乎更常见。动态分配通常发生在更高级别,然后调用函数,其中setjmp出现。)

c performance memory-leaks setjmp

6
推荐指数
1
解决办法
2467
查看次数

setjmp并省略帧指针

我一直试图在我的代码中查找间歇性崩溃错误(使用setjmp),并将其缩小为:在使用/ O2进行编译时显示,使用/ O2/Oy-消失,即仅显示省略帧指针.

http://msdn.microsoft.com/en-us/library/2kxx5t2c(v=vs.80).aspx建议setjmp需要一个帧指针.从而:

  1. 似乎当使用/ O2编译使用setjmp的程序时,Visual C++会静默生成导致间歇性堆栈损坏的代码.这是真的吗,还是我错过了什么?

  2. 在我看来,只有调用setjmp的函数才需要用帧指针编译,程序的其余部分 - 甚至是调用longjmp的函数 - 应该可以省略帧指针.这是真的?

编辑:我把它缩小了一点.

在调用setjmp的函数上启用帧指针没有任何区别,但那是因为编译器已经这样做了,就像它应该的那样,显然注意到它需要完成,并自动完成.

有什么区别是在主要上启用帧指针.这并不像听起来那么奇怪,因为坠机是从主要的回归中显现出来的.现在,我想到了它,我可以在快速谷歌搜索setjmp使用中找到的所有示例,在main中执行.也许碰巧Microsoft编译器团队只是以这种方式测试它.

这是使用它的惯用方法,也许最好的解决方法是让我将setjmp-using函数内联到main中.

c visual-c++ longjmp setjmp

5
推荐指数
1
解决办法
855
查看次数

使用setjmp和longjmp时,jmp_buf中的实际内容是什么?

setjmp()应该将包含"返回地址"和"堆栈指针"的寄存器保存到"jmp_buf"中.当我编译(gcc和clang)并使用glibc在x86_64下调试以下程序时,我无法理解"jmp_buf"中的内容以及"返回地址"和"堆栈指针"位于"jmp_buf"中的位置.

#include <stdio.h>
#include <setjmp.h>

int main()
{
    int i;

    jmp_buf env;

    i = setjmp(env);

    printf("i = %d\n", i);

    if (i != 0) return;

    longjmp(env, 2);
    printf("Does this line get printed?\n");
}   
Run Code Online (Sandbox Code Playgroud)

当程序在"printf("i =%d \n",i);"之前的断点处停止时,我尝试了gdb功能:"p/x env"; 但是我在这个包含__jmpbuf和__saved_mask的结构(env)中找不到"返回RIP"和"之前的RSP".任何人都知道这两个函数究竟是如何工作的以及它们在x86_64下用glibc保存的是什么(我使用的是ubuntu 14.04)?

c debugging gdb longjmp setjmp

5
推荐指数
1
解决办法
1743
查看次数

glibc的setjmp代码在哪里?

我对setjmp至少在x86_64 linux中究竟做了什么感兴趣,所以我搜索了glibc源代码,但我无法真正找到寄存器保存的位置.你能解释一下这里发生了什么吗?

SETJMP.H

extern int _setjmp (struct __jmp_buf_tag __env[1]) __THROWNL;
#define setjmp(env)     _setjmp (env)
Run Code Online (Sandbox Code Playgroud)

BSD-_setjmp.c

int
_setjmp (jmp_buf env)
{
  return __sigsetjmp (env, 0);
}

libc_hidden_def (_setjmp)
Run Code Online (Sandbox Code Playgroud)

setjmp.c

int
__libc_sigsetjmp (jmp_buf env, int savemask)
{
  __sigjmp_save (env, savemask);
  __set_errno (ENOSYS);
  return 0;
}

weak_alias (__libc_sigsetjmp, __sigsetjmp)
stub_warning (__sigsetjmp)
Run Code Online (Sandbox Code Playgroud)

sigjmp.c

int
__sigjmp_save (sigjmp_buf env, int savemask)
{
  env[0].__mask_was_saved = (savemask &&
                             __sigprocmask (SIG_BLOCK, (sigset_t *) NULL,
                                            &env[0].__saved_mask) == 0);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

c setjmp

5
推荐指数
1
解决办法
855
查看次数

C中的递归协同程序(C99)

在实现通信协议时,我们有一个编码器,它以递归方式遍历某些结构并将它们编码为二进制消息.

到目前为止一直很好,但现在缓冲区必须分成多个固定大小的块,例如接收缓冲区的大小.因为为完整消息分配内存并因此削减它似乎太浪费了(消息的大小 - 理论上 - 没有限制),现在的想法是用setjmp/longjmp实现协同程序.

目前,我有一个带有两个跳转缓冲区的原型 - 一个用于恢复编码功能的缓冲区,另一个用于模拟函数的返回行为以跳回其调用者.

好吧,它似乎工作,但代码看起来像直接来自地狱.是否存在用于实现可中断递归函数的"约定",可能是一组宏或什么?我想只使用标准化的功能,没有内联asm以便保持便携.

增加: 原型在这里:https://github.com/open62541/open62541/compare/master...chunking_longjmp '用法'显示在单元测试中.目前,针对非递归函数实现了协程行为Array_encodeBinary.但是,'coroutine'行为应该扩展到UA_encodeBinary这里的一般递归函数:https://github.com/open62541/open62541/blob/master/src/ua_types_encoding_binary.c#L1029

c recursion coroutine longjmp setjmp

5
推荐指数
1
解决办法
347
查看次数

在没有内置函数或程序集的情况下在C中实现setjmp和longjmp(获取不正确的返回值)

我正在尝试测试我的两个函数,它们模仿setjmp和longjmp用于作业 - 这是非常困难的,因为我们不允许使用内置函数或汇编asm()来实现longjmp和setjmp函数.(是的,那真的是作业.)

问题:我一直收到错误的返回值.所以,简而言之,当main()调用foo()和foo()调用bar(),而bar()调用longjump()时,bar()不应该返回foo(),而是setjmp()应该返回main的返回值为1,应打印"error"(参见下面的main()).

相反,我的输出结果如下:

start foo
start bar
segmentation fault
Run Code Online (Sandbox Code Playgroud)

分段错误,我尝试通过使用malloc初始化指针*p来修复,但似乎没有做任何事情.虽然,分段错误,是我没有得到正确的返回值的原因?

码:

#include <stdio.h>
#include <stdlib.h>

int setjmp(int v);
int longjmp(int v);
int foo(void);
int bar(void);
int *add;


int main(void) {

    int r;

    r = setjmp(r);
    if(r == 0) {
        foo();
        return(0);
    } else {
        printf("error\n");
        return(2);
    }

}

int _main(void) {
    return(0);
}

int setjmp(int v)
{
    add = &v;
    return(0);
}

int longjmp(int v)
{
    int *p;
    p = &v;
    *(p - 1) = …
Run Code Online (Sandbox Code Playgroud)

c stack pointers longjmp setjmp

5
推荐指数
1
解决办法
1415
查看次数