31 May, 2010, Mudder wrote in the 1st comment:
Votes: 0
/*
* 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.
31 May, 2010, Kline wrote in the 2nd comment:
Votes: 0
See Tyche's explanation here (no, not needed): [link=post]5263[/link]
31 May, 2010, Runter wrote in the 3rd comment:
Votes: 0
My first instinct is to say no, this is not necessary. I haven't used this or anything like this in the C projects I've been involved with.
31 May, 2010, quixadhal wrote in the 4th comment:
Votes: 0
Regarding tail_chain…..

It was a workaround for an old bug/optimization in gcc 2.95 (I think) which screwed up the backtrace stack. Essentially, if you called a function from another function that didn't return a value (IE: void), the compiler would generate code that would jump you into that function's code instead of actually using the call stack. This was supposed to be more efficient (not saving/restoring registers for the function call), but of course it also meant the debugger didn't have such things to help it track your code.

So, adding a tail_chain() function that did nothing forced the optimization to not be used (because the function you put the tail_chain in now called something else, so it couldn't just be jumped to).

I may be wrong, of course, but that's how I understood it. I'm pretty sure gcc 3.x changed the architecture enough to make that practice obsolete.

Regarding Samson: It was probably not a good idea to actually physically delete his (or ANY) account, as it causes data integrity problems (as you're not seeing). Disk space is cheap. If you can, always just mark people as inactive and make them invisible if you don't want them to be seen.

We always did that with our systems. We had cascade deletes, but nothing in code ever removed things…. the idea was that it's safer to mark folks inactive and then go through and hand check what *would* get nuked by the cascade delete if you ran it, just to be sure it wouldn't take out half the system. :)

Orrin edit: I've split the user deletion discussion to this thread.
31 May, 2010, Tyche wrote in the 5th comment:
Votes: 0
AFAIK nothing's changed. The example posted earlier on the other thread was from gcc 3.3.x
On gcc 4.3.x the optimization was moved back to -O2 level:

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)


I think the problem has always been a user issue.
0.0/5