longjmp/setjmp 与 volatile 的安全使用

Safe usage of longjmp/setjmp with volatile

我考虑使用基于 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 是可变的,而前面的声明使指针可变?

u32 *volatile var 使 指针 可变,而 volatile u32 *var 告诉编译器该地址的数据是可变的。因此,由于在后一个示例中指针不是可变的,如果您的编译器将 default 案例完全优化为 result = NULL;.

之类的东西,我不会感到惊讶。

它可能不会期待 setjmp 魔法,而且这些甚至因 "more spaghetti than goto" 而臭名昭著。