Почему gdb показывает два различных возврата?

На прошлой неделе я был отладкой кода, и подошла странная ситуация: gdb проходит через два различных пункта возврата. Я сделал простой пример, который иллюстрирует ситуацию:

#include <iostream>

using namespace std;

int test() {

    string a = "asd";
    string b = "asd";

    while (true) {
        if (a == b) {
            return 0;
        }
    }
    return -1;
}

int main() {
    int result = test();
    cout << "result: " << result << endl;
}

При отладке кода я добрался:

(gdb) b main
Breakpoint 1 at 0x1d4c: file example.cpp, line 19.
(gdb) r
Starting program: /Users/yuppienet/temp/a.out 
Reading symbols for shared libraries +++. done

Breakpoint 1, main () at example.cpp:19
19          int result = test();
(gdb) s
test () at example.cpp:7
7           string a = "asd";
(gdb) n
8           string b = "asd";
(gdb) n
11              if (a == b) {
(gdb) n
12                  return 0;
(gdb) n
15          return -1;
(gdb) n
16      }
(gdb) n
main () at example.cpp:20
20          cout << "result: " << result << endl;
(gdb) n
result: 0
21      }
(gdb) n
0x00001ab2 in start ()

Я отметил, что, даже если gdb показывает строку 15, возвращаемое значение 0 ( finish команда подтверждает это также).

Таким образом, вопрос: почему делает выставочную строку gdb 15: return -1, даже если функция действительно не возвращает это значение?

Спасибо!

Править: Я забыл упоминать, что я скомпилировал со следующей строкой:

g++ -Wall -pedantic -g -pg example.cpp
7
задан Deanie 29 May 2016 в 20:26
поделиться

3 ответа

Я подозреваю, что вы видите эпилог функции. У ваших двух строк есть деструкторы, которые неявно вызываются при возврате. Проверьте, что говорит дизассемблер, чтобы быть уверенным, но я подозреваю, что оба оператора return отображают что-то вроде:

stash return_value;
goto epilogue;

и, соответственно:

epilogue: 
  destroy a; // on the stack, so destructor will be called
  destroy b;
  really_return(stashed value);

Эпилог, похоже, исходит из строки 15 как побочный эффект того, как g ++ выполняет нумерацию строк - довольно простой формат, на самом деле просто список тегов в форме «адрес X происходит из строки с номером Y» - и поэтому он сообщает 15 как самое близкое совпадение. В данном случае это сбивает с толку, но часто поправляет.

4
ответ дан 7 December 2019 в 03:12
поделиться

Возможно, потому что регистр программного счетчика проходит через инструкции, которые лучше всего соответствуют окончательному возврату, т.е. последовательности выхода функции. Фактическое значение возврата, вероятно, хранится в регистре, поэтому первый return просто загружает нужное значение и переходит в конец функции, а затем этот адрес "привязывается" к строке исходного кода финального return.

3
ответ дан 7 December 2019 в 03:12
поделиться

Вы не говорите, но если вы скомпилировали с оптимизацией, это в точности то поведение, которое вы могли бы увидеть в gdb. Вы видите, что первая строка устанавливает возвращаемое значение, а затем она переходит к реальной инструкции возврата, но в C ++ вы видите все, включая возвращаемое значение.

2
ответ дан 7 December 2019 в 03:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: