void foo() {
rand(9);
}
int main() {
foo();
}
jlambert@atlas ~
$ gcc -O3 -g tail.c -o tailO3
jlambert@atlas ~
$ gcc -O2 -g tail.c -o tailO2
jlambert@atlas ~
$ gcc -O1 -g tail.c -o tailO1
jlambert@atlas ~/oldhome
$ gdb ./tailO3
(gdb) break main
Breakpoint 1 at 0x401161: file tail.c, line 4.
(gdb) run
Starting program: /home/jlambert/tailO3
Breakpoint 1, main () at tail.c:4
4 int main() {
(gdb) bt
#0 main () at tail.c:4
(gdb) s
2 rand(9);
(gdb) bt
#0 main () at tail.c:2
(gdb) s
6 }
(gdb) bt
#0 main () at tail.c:6
$ gdb ./tailO2
(gdb) break main
Breakpoint 1 at 0x401161: file tail.c, line 4.
(gdb) run
Starting program: /home/jlambert/tailO2
Breakpoint 1, main () at tail.c:4
4 int main() {
(gdb) bt
#0 main () at tail.c:4
(gdb) s
2 rand(9);
(gdb) bt
#0 main () at tail.c:2
(gdb) s
6 }
(gdb) bt
#0 main () at tail.c:6
$ gdb ./tailO1
(gdb) break main
Breakpoint 1 at 0x401155: file tail.c, line 4.
(gdb) run
Starting program: /home/jlambert/tailO1
Breakpoint 1, main () at tail.c:4
4 int main() {
(gdb) s
5 foo();
(gdb) bt
#0 main () at tail.c:5
(gdb) s
foo () at tail.c:2
2 rand(9);
(gdb) bt
#0 foo () at tail.c:2
#1 0x0040115f in main () at tail.c:5
(gdb) s
3 }
(gdb) bt
#0 foo () at tail.c:3
#1 0x0040115f in main () at tail.c:5
(gdb) s
main () at tail.c:6
6 }
(gdb) bt
#0 main () at tail.c:6
(gdb)
* This function is here to aid in debugging.
* If the last expression in a function is another function call,
* gcc likes to generate a JMP instead of a CALL.
* This is called "tail chaining."
* It hoses the debugger call stack for that call.
* So I make this the last call in certain critical functions,
* where I really need the call stack to be right for debugging!
*
* If you don't understand this, then LEAVE IT ALONE.
* Don't remove any calls to tail_chain anywhere.
*
* – Furey
*/
void tail_chain( void )
{
return;
}
In ROM codebases this is sprinkled all around. Is this "tail chaining" effect still a current problem with gcc or g++ compilers?
To me it just seems unnecessary and silly.