the principal raison d'etre of abort is to die with a core dump (typically on failed assertions). I am not the only person who spent days of useless post-mortem debugging (or debugging with a breakpoint on abort) because of gcc's optimization of -fcross-jumping, which means that gcc recycles a single abort call (with inconsistent stack state) all across a function. That means that the core dump has _both_ incoherent and unexpected stack state, as well as pointing to a completely wrong position in the source file. The principal purpose of the noreturn attribute is to allow for inconsistent stack state and call recycling. So its effects, if any, are directly in conflict with the purpose of abort, an unorderly exit with the main purpose to facilitate debugging. While technically abort _does_ not return, telling the compiler so is giving it leave to eradicate its call history. And that is not useful at all when debugging. Since the presence of -g should not alter the code, abort should not be marked noreturn.
To add some more substance: I know of at least 5 different Emacs developers who have independently wasted in the order of days making sense of failed assertions because of the useless state of the stack frame for post mortem debugging. The file DEBUG in the Emacs distribution contains the advice to compile with -fno-crossjumping which helps somewhat (but most people only read this after having wasted a lot of time). So this problem is not academical. It would be nice to at least get some sort of minimal feedback.
This is wrong and will break any function that has a non void return type and that specify that code is unreachable using abort(), without "returning" anything after abort(). This is perfectly valid code, there is quite a lot of it out there, and such a change would gratuitously break it.
Changing glibc to make debugging easier at the cost of speed or cost size won't happen. *Especially* since there are work arounds. Just add the gcc flag.
(In reply to comment #2) > This is wrong and will break any function that has a non void return type and > that specify that code is unreachable using abort(), without "returning" > anything after abort(). How will it "break" anything? Unreachable code is not forbidden by any C standard as far as I know. > This is perfectly valid code, there is quite a lot of it out there, and such a > change would gratuitously break it. Perfectly valid according to which C standard? Can you give an example for code which would rely on the noreturn optimization and would fail without it? (In reply to comment #3) > Changing glibc to make debugging easier at the cost of speed or cost size won't > happen. *Especially* since there are work arounds. Just add the gcc flag. Let me put this more bluntly: the current behavior breaks abort's principal functionality. abort raises SIGABRT. The default action for SIGABRT is Signal Value Action Comment ---------------------------------------------------------------------- SIGABRT 6 Core Abort signal from abort(3) So the default action is a core dump, and the core dump is junk when gcc performs noreturn optimizations. If people don't want a core dump, they will use exit(255) instead of abort. We are not talking about "making debugging easier". We are talking about abort being able to function as intended at all. If you don't consider it appropriate to remove the noreturn attribute (which is an expedience), you might consider implementing an attribute "uniquecall" or "debug" or so which will basically enable "-fno-crossjumping" just for calls of abort. In that manner, the core dump at least points to a unique call point for abort, and it becomes theoretically possible for the compiler/debugger combo to untangle any noreturn optimizations that have been done at that particular call point. If the abort call can be jumped to from several different locations (possibly even different functions), untangling the stack frame becomes no longer possible and the core dump, the principal output of abort, is useless.
Stop reopening. You have your remedy, you're just too lazy to do any work yourself and so would rather see everyone suffer. And > Let me put this more bluntly: the current behaviour breaks abort's principal > functionality. is of course total nonsense. The main functionality is to abort the process and that is done.
The ISO C std 9899:1999, Sec 7.20.4.1 makes it clear: The specification of abort() is void abort(void); and under "Returns" is the single sentence: The abort function does not return to its caller. IEEE POSIX 1003.1-2001 reiterates the above. I hope this answers the questions concerning the specification, and why we intend to remain in conformance.
(In reply to comment #6) > The ISO C std 9899:1999, Sec 7.20.4.1 makes it clear: > The specification of abort() is > void abort(void); > and under "Returns" is the single sentence: > The abort function does not return to its caller. > > IEEE POSIX 1003.1-2001 reiterates the above. I hope this answers the questions > concerning the specification, and why we intend to remain in conformance. Huh? Nobody suggested letting abort return to its caller. My proposal has nothing whatsoever to do with complying or not complying to the above spec. The SPEC does _not_ state "The optimizer should ensure that abort is entered with a stack state not containing useful information for the ensuing core dump". Yes, certainly abort should not return. But making use of this information in the current manner means that abort is called without an identifiable call context and associated identifiable register/stackframe/value state. And for a function with the distinguishing feature of creating a core dump, that's a rather hefty drawback. The resulting core dump is quite often useless, and not useless in the usual "things may get executed and assigned in strange orders" sense, but rather in the "utter garbage masquerading as something sensible and wasting you hours of head-scratching" sense.
Removing noreturn from abort will not eliminate the problem, the compiler will still combine two calls if they appear in similar enough contexts. In the following example the compiler will still generate only a single call to abort, no matter how it is declared. #include <stdlib.h> int bar (int); #ifdef USE_ABORT1 void abort1 (void); #define abort abort1 #endif int foo (int a) { int b; if (a == 1) { b = bar (a); if (!b) abort (); } else if (a == 2) { b = bar (a + 1); if (!b) abort (); } else b = a; return b; }
(In reply to comment #8) > Removing noreturn from abort will not eliminate the problem, the compiler will > still combine two calls if they appear in similar enough contexts. Quite correct. However, this will occur at a junction of the code paths with compatible and recognizable stack frame. So the inconvenience is more or less "par for optimization". You will still be able to examine variable values (even if they move through registers) and figure out what function you are in. The optimal solution would, as I stated at the bottom of comment #4, introduce some attribute that could effectively enable -fno-crossjumping for abort calls only. In that manner, the "noreturn" optimizations would have a chance to be tracked by debugging information since the return address would uniquely identify the context of the stack frame. This would require work in the compiler and might be the most elegant solution in the long run. Leaving off "noreturn" in the meantime would provide an expedience that gets rid of the most productivity-wasting artifacts. If nothing is done at all, at least the GCC documentation would warrant a strong warning about the particular effects of the (standard for -O) -fcrossjumping option on post mortem debugging.
Subject: Re: abort should not be marked noreturn On Tue, 17 Jun 2008, dak at gnu dot org wrote: > The optimal solution would, as I stated at the bottom of comment #4, introduce > some attribute that could effectively enable -fno-crossjumping for abort calls > only. In that manner, the "noreturn" optimizations would have a chance to be > tracked by debugging information since the return address would uniquely > identify the context of the stack frame. > > This would require work in the compiler and might be the most elegant solution > in the long run. Leaving off "noreturn" in the meantime would provide an > expedience that gets rid of the most productivity-wasting artifacts. The compiler provides a noreturn attribute for abort automatically. Whether the header provides it doesn't matter unless you use -fno-builtin-abort.
(In reply to comment #10) > The compiler provides a noreturn attribute for abort automatically. > Whether the header provides it doesn't matter unless you use > -fno-builtin-abort. That would suggest that this report should better have been filed with GCC than with glibc since it would seem that a header change will usually not make a dfference. Thanks for that information, appreciated. Now I can move elsewhere in order to let my head bashed in.