2016-09-12 2 views
4

Я рассматриваю использование макроса TRY/CATCH на основе setjmp/longjmp для обработки ошибок. В противном случае некоторые из моих вполне структурированных функций будут взорваны уродливыми операторами if и флагами цикла.Безопасное использование longjmp/setjmp с volatile

Код как в этом примере:

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; 
} 

БРОСОК фактически макрос

#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) 

Проблема:

Когда исключение (например, я = 1) указатель var сбрасывается в NULL, хотя я использовал ключевое слово volatile, которое должно избегать использования для него регистра. Из отладчика я вижу, что это все еще в регистре, а не в памяти.

Я допустил ошибку?

EDIT:

Я изменил декларацию вар в

uint32_t * volatile var = NULL; 

Это работает ;-)

Я не очень понимаю, в чем разница:

volatile uint32_t * var = NULL; 

средства , что VALUE нестабильна, тогда как прежняя декларация делает указатель изменчивым?

+0

Когда я компилирую этот код и 'printf ("% d \ n ", trycatchtest (1));' он возвращает '11' ... Как вы скомпилировали и какие флаги вы использовали? – tversteeg

+0

Я согласен с @tversteeg, он работает и на моей машине. Какой компилятор/платформа это? Как определяется 'os_malloc', предположительно, вы делаете какие-то вложенные/RTOS-материалы? – Groo

+0

см. Мое редактирование выше! – michael

ответ

1

u32 *volatile var делает указателя летучих, в то время как volatile u32 *var сообщает компилятор, что данные по этому адресу неустойчивые. Так как указатель не является волатильным в последнем примере, я не удивлюсь, если ваш компилятор полностью отключит корпус default примерно на result = NULL;.

Это, вероятно, не ожидает волшебства setjmp, и они известны тем, что являются «более спагетти, чем goto».

+0

Бесконечная дискуссия о том, какой стиль лучше всего подходит для обработки ошибок в C. Поскольку я использую макросы только для обработки ошибок в больших тестовых процедурах, они делают жизнь более простой для меня. – michael

+0

http://stackoverflow.com/questions/14685406/practical-usage-of-setjmp-and-longjmp-in-c – michael

Смежные вопросы