[EMAIL PROTECTED] (Steven Bosscher) wrote on 13.03.05 in <[EMAIL PROTECTED]>:
> On Sunday 13 March 2005 02:07, James E Wilson wrote: > > Richard Stallman wrote: > > > Currently, I believe, GCC combines various calls to abort in a single > > > function, because it knows that none of them returns. > > > > To give this request a little context, consider the attached example. > > May I recommend KMail, the mailer that complains when you say you > attached something, and you didn't? :-) > > > Otherwise, we need to consider the merits of disabling an optimization > > to make debugging easier. This is a difficult choice to make, but at > > -O2, I'd prefer that we optimize, and suggest other debugging techniques > > intead of relying on the line numbers of abort calls. Such as using > > assert instead. > > Right. Really, abort() is just the wrong function to use if you > want to know *where* a problem occured. GCC uses this fancy_abort > define: > > system.h:#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__) > > where fancy_abort() is a, well, fancy abort that prints some more > information about what happened, and where. IMVHO any moderately > large piece of software that uses abort should consider using this > kind of construct, or use assert(). Crippling optimizers around > abort is just silly. It's attacking a real problem from the wrong > end. The real problem is that abort() is just not detailed enough. For what little it's worth, I agree completely. In any significant C- family project, I always have macros to handle these things - usually significantly more involved that your example. In a certain Objective-C project, I even have Perl-generated Exceptions.[hm] so a number of different error situations can be handled by similar syntax. For example, for errno-setting cases, I have extern NSString *OSException; extern NSString *NameOSError(int Eerrno); extern void RaiseOSException(int Eerrno, const char *Efile, int Eline, const char *Efunc, const char *Econd, NSString *Efmt, ...); #define RAISE_OS_R(_cond, _fmt, _info...) do { int _err = errno; \ RaiseOSException(_err, __FILE__, __LINE__, __PRETTY_FUNCTION__, \ #_cond, _fmt ,##_info); } while (0) #define RAISE_OS_I(_cond, _fmt, _info...) do { if (_cond) \ RAISE_OS_R(_cond, _fmt ,##_info); } while (0) so I can then write RAISE_OS_I(fseeko(AdrF, 0, SEEK_END) != 0, AdrFName); or Recs = fopen(StringToCP(Data, CP_fs), "r+b"); if (!Recs && errno == ENOENT) { ... } else { if (!Recs) RAISE_OS_R("fopen(StringToCP(Data, CP_fs), \"r+b\")", Data); ... } or even, if the situation doesn't call for an exception, [errors addObject: [NSString stringWithFormat: @"%@: error opening: %@", fd->name, NameOSError(err)]]; And yes, ultimately, if the exception isn't caught before, there will be an abort(): static void __attribute__((__noreturn__)) Panic(const char *f, int l) { Cprintf("<-\n\rPanic at %s:%d\n\r", f, l); fflush(stderr); shutdownConsole(); abort(); } ... with another reference to what logic decided not to continue after all. Most of the rest of the error handling in this project is concerned with the absence of the feature I loved in the IBM PL/I compilers under the name "SNAP;" - putting out a stack backtrace (the usual idiom for abort() was "SNAP; STOP;" IIRC). Now *that* would be a useful feature to have. Seems to me these days it shouldn't be all that hard based on dwarf2 debug info ... too bad I still am in 2.95.4 land. I will probably try to go straight to 4.0 or 4.1 one of these days, depending on how reliable it seems and how much time I get - there are a number of features I'd like to have. Possibly that could also help my home-grown profiling code (which works for threaded code under both Linux and Windows, which I could get none of the "standard" versions to do - triggering off -finstrument- functions - but doesn't give as nice info as gprof). MfG Kai