【问题标题】:Safe usage of longjmp/setjmp with volatilelongjmp/setjmp 与 volatile 的安全使用
【发布时间】:2016-09-12 07:49:52
【问题描述】:

我考虑使用基于 setjmp/longjmp 的 TRY/CATCH 宏来进行错误处理。否则我的一些相当结构化的函数会被丑陋的 if 语句和循环标志炸毁。

代码是这样的例子:

int trycatchtest(int i)
{
    int result = 0;
    volatile int error = 100;
    volatile uint32_t *var = NULL;
    TRY
    {
        error = 0;
        var = os_malloc(4);
        *var = 11;
        if (i) THROW( i );
    }
    FINALLY
    {
        result = *var;
    }
    END;
    return result;
}

THROW 其实就是宏

#define TRY do { jmp_buf buf; switch( setjmp(buf) ) { case 0:     while(1) {
#define FINALLY break; } default: {
#define END break; } } } while(0)
#define THROW(x) longjmp(buf, x)

问题:

当抛出异常时(例如 i=1),指针 var 被重置为 NULL,尽管我使用了 volatile 关键字,这应该避免使用寄存器。从调试器中我看到它仍在寄存器中,而不是在内存中。

我做错了吗?

编辑:

我将 var 的声明改为

uint32_t * volatile var = NULL;

这行得通;-)

我不太明白有什么区别:

volatile uint32_t * var = NULL;

意思是,VALUE是volatile的,而前面的声明使得指针是volatile的?

【问题讨论】:

  • 当我编译这段代码和printf("%d\n", trycatchtest(1));它返回11...你是如何编译的,你使用了什么标志?
  • 我同意@tversteeg,它也适用于我的机器。这是哪个编译器/平台? os_malloc 是如何定义的,大概你在做一些嵌入式/RTOS 的东西?
  • 在上面查看我的编辑!
  • 这是一些非常丑陋和危险的代码。不要这样写废话,它比“on error goto”模式要糟糕得多。这又比“函数返回错误代码”更糟糕。
  • 我同意@Lundin,“on error goto”模式(例如,在 Linux 内核源代码中广泛使用)比这种废话更可取。您的 trycatchtest 函数似乎存在内存泄漏,尽管您仅使用它来测试您的宏。由于buf是一个局部变量,这些宏在嵌套的函数调用中不起作用,那么为什么需要为这些宏使用setjmp/longjmp呢?

标签: c exception-handling setjmp


【解决方案1】:

u32 *volatile var 使 指针 易失,而 volatile u32 *var 告诉编译器该地址处的数据是易失的。因此,由于在后一个示例中指针不是易失性的,因此如果您的编译器将default 的情况完全优化为result = NULL; 之类的情况,我不会感到惊讶。

它可能不会想到 setjmp 的魔法,而这些魔法甚至因为“比 goto 更意大利面”而臭名昭著。

【讨论】:

  • 关于哪种风格最适合 C 中的错误处理,这是一场永无休止的争论。因为我只在大型测试例程中使用宏来处理错误,它们让我的生活变得更简单。跨度>
猜你喜欢
  • 2015-12-10
  • 1970-01-01
  • 2023-03-12
  • 2011-12-21
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多