Переменная внутри блока if отображается в стеке вызовов, хотя оператор if не был оценен как true - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть кусок кода на C, как показано ниже -

В файле .c-

1    custom_data_type2 myFunction1(custom_data_type1 a, custom_data_type2 b)
2    {
3        int c=foo();
4        custom_data_type3 t;
5        check_for_ir_path();
6        ...
7        ...
8    }
9
10    custom_data_type4 myFunction2(custom_data_type3 c, const void* d)
11    {
12        custom_data_type4 e;
13        struct custom_data_type5 f;
14        check_for_ir_path();
15        ...
16        temp = myFunction1(...);
17        return temp;
18    }

В заголовочном файле -

1    void CRASH_DUMP(int *i)
2     __attribute__((noinline));
3    
4    #define INTRPT_FORCE_DUMMY_STACK    3
5    
6    #define check_for_ir_path() { \
7        if (checkfunc1() && !checkfunc2()) { \
8            int temp = INTRPT_FORCE_DUMMY_STACK; \
9            ...
10            CRASH_DUMP(&sv);\
11        }\
12    }\

При неизвестном сценарии происходит сбой. После обработки дампов ядра с помощью GDB мы получаем стек вызовов как -

#0  0x00007ffa589d9619 in myFunction1 [...] 
(custom_data_type1=0x8080808080808080, custom_data_type2=0x7ff9d77f76b8) at ../xxx/yyy/zzz.c:5

        temp = 32761

        t = <optimized out>



#1  0x00007ffa589d8f91 in myFunction2 [...]

(custom_data_type3=<optimized out>, d=0x7ff9d77f7748) at ../xxx/yyy/zzz.c:16

        temp = 167937677

        f = {

          ...

        }

Если вы видите код, check_for_ir_path вызывается из myFunction1() и myFunction2().

А внутри check_for_ir_path внутри блока есть проверка, например, - checkfunc1() && !checkfunc2(). Если эта проверка оценивается как ИСТИНА, то запускается SIGSEGV, и процесс намеренно завершается сбоем. И переменная temp объявляется, только если это условие выполняется.

Теперь, если вы посмотрите на стек вызовов, вы увидите локальную переменную temp, показанную даже в StackFrame_1 . Однако это не вылетало внутри функции myFunction2. Как это могло быть возможно?

Если я объявляю другую переменную, скажем «int temp» сразу после инструкции int temp = INTRPT_FORCE_DUMMY_STACK;, она не отображается как часть bt full

Как это вообще возможно?

1 Ответ

0 голосов
/ 04 сентября 2018

Компиляторам разрешается реорганизовать ваш код любым способом, который не изменит результат программы. Так что если вы напишите:

void foo()
{
    if (something)
    {
        int sv;
        ...
    }
}

компилятору разрешено изменять его на что-то эквивалентное:

void foo()
{
    int sv;
    if (something)
    {
        ...
    }
}

независимо от того, является ли something истинным или ложным.

Но компилятор должен убедиться, что это не удастся скомпилировать:

void foo()
{
    if (something)
    {
        int sv;
        ...
    }
    sv = whatever;  // Compiler error....
}
...