Почему трассировка стека пропускает функцию, которая, очевидно, должна быть вызвана для достижения следующих функций?

Учитывая такую ​​настройку, где вызывается DoFooStuff ():

class Foo {
public:
void DoFooStuff(); // calls Bar::DoBarStuff()
}

class Bar {
public:
void DoBarStuff(); // Calls Bar::DoInternalBarStuff()
protected:
void DoInternalBarStuff();
}

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

Type                   Function
void                   Bar::DoInternalBarStuff()
void                   Foo::DoFooStuff()

Единственная ссылка на DoInternalBarStuff () находится в DoBarStuff (). DoInternalBarStuff () утверждает в своей первой строке:

assert(false);

И это то место, откуда берется трассировка стека.

1

Решение

Является ли вызов Bar :: DoBarInternalStuff последним оператором в Bar :: DoBarStuff? Если это так, компилятор, скорее всего, заменил стековый фрейм Bar :: DoBarStuff на Bar :: DoBarInternalStuff, когда вызывался Bar :: DoBarInternalStuff.

Этот вид хвостовой вызов оптимизация довольно распространена в компиляторах C / C ++. Это уменьшает глубину стека, необходимую, когда рекурсивная функция может быть организована таким образом, что рекурсивный вызов является последним вызовом функции.

4

Другие решения

Получается, что компилятор выполняет автоматическое встраивание на определенных уровнях оптимизации. Учиться новым вещам каждый день. 🙂

Работает ли GCC inline C ++ без ключевого слова inline?

(Спасибо за полезные комментарии, которые показали мне это.)

0