![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
> Nicolas Alvarez wrote:
>> Darren New wrote:
>>> I wasn't aware C++ even defined tracebacks on exceptions.
>>
>> It doesn't.
>
> Then the traceback in your exceptions can't tell you the values, can it?
Exceptions have no "traceback" directly visible at runtime from inside the
code. You can use platform-specific code in an exception handler to get a
stack trace (by following stack pointers).
>>> How does one access that feature?
>> Through your debugger :)
>
> I don't really want to tell my customers to run my production code under a
> debugger and copy/paste the traceback into the logfile before sending it
> to me.
KDE has a crash handler similar to Windows's, except it can't automatically
send the report back to the developer. It gives you a stacktrace, including
all the function parameters, and lets you save the file to upload to the
bug tracker.
When an application crashes, the crash handler *attaches* a debugger to the
just-segfaulted app, loads the debugging symbols from a different file,
gets a stacktrace, and lets the crashed app die and R.I.P.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Nicolas Alvarez wrote:
> Darren New wrote:
>> In C++, you can write
>> alpha beta(gamma);
> You're calling alpha constructor.
How do you know you're not declaring a function beta that take an argument
of type gamma and returns an alpha?
--
Darren New, San Diego CA, USA (PST)
My fortune cookie said, "You will soon be
unable to read this, even at arm's length."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Nicolas Alvarez wrote:
> Darren New wrote:
>> Nicolas Alvarez wrote:
>>> Darren New wrote:
>>>> I wasn't aware C++ even defined tracebacks on exceptions.
>>> It doesn't.
>> Then the traceback in your exceptions can't tell you the values, can it?
>
> Exceptions have no "traceback" directly visible at runtime from inside the
> code.
That's what I was saying.
> You can use platform-specific code in an exception handler to get a
> stack trace (by following stack pointers).
And that's what I asked - what would I google on to see this, given it's not
defined in exception.h? What's it called?
> When an application crashes, the crash handler *attaches* a debugger to the
> just-segfaulted app, loads the debugging symbols from a different file,
> gets a stacktrace, and lets the crashed app die and R.I.P.
Of course, it helps that it's crashing, instead of trying to actually do
something about the problem, I suppose. And that most systems will have a
debugger installed already.
--
Darren New, San Diego CA, USA (PST)
My fortune cookie said, "You will soon be
unable to read this, even at arm's length."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
> And that's what I asked - what would I google on to see this, given it's
> not defined in exception.h? What's it called?
It's not directly related to exceptions, since it's a C API (not C++).
GNU libc (not libstdc++!) has C functions to get backtraces at any moment.
It's a GNU extension. You may very well call it in an exception handler.
http://www.gnu.org/software/libtool/manual/libc/Backtraces.html
The Windows API has similar functionality through the DlgHelp module,
especially the StackWalk64() and SymFromAddr() functions.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> that objects could register themselves to some centralized, non-template
> factory, using their own typeid as key, so that the factory could create
> clones of those objects at runtime, based on those typeids.)
Actually, wouldn't this be clearer to do with virtual functions or pointers
to functions anyway? Where does typeid make things better in that scenario?
Isn't it just as easy to do something like
class Alpha : Beta {
....
virtual const char * me() { return "Alpha:Beta"; }
....
}
and switch on that? That even gives you a defined value, so you can (say)
write it into a file and read it back on the next run to reload objects that
serialized themselves or something. Plus, you avoid the overhead of putting
RTTI type_info on *every* class, most of which probably won't be registered
that way?
--
Darren New, San Diego CA, USA (PST)
My fortune cookie said, "You will soon be
unable to read this, even at arm's length."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
> Warp wrote:
>> that objects could register themselves to some centralized, non-template
>> factory, using their own typeid as key, so that the factory could create
>> clones of those objects at runtime, based on those typeids.)
>
> Actually, wouldn't this be clearer to do with virtual functions or
> pointers to functions anyway? Where does typeid make things better in that
> scenario? Isn't it just as easy to do something like
>
> class Alpha : Beta {
> ....
> virtual const char * me() { return "Alpha:Beta"; }
> ....
> }
>
> and switch on that? That even gives you a defined value, so you can (say)
> write it into a file and read it back on the next run to reload objects
> that serialized themselves or something.
I think the most useful feature of RTTI is not typeid() to get a string, but
dynamic_cast.
void foo(Alpha* ptr) {
Beta* beta = dynamic_cast<Beta*>(ptr);
}
If ptr is a Beta object that was (maybe implicitly) cast to a Alpha*, then
beta is now equal to ptr (except its type is Beta*, so you can use Beta
members). If ptr actually pointed to an Alpha, or a Delta (another subclass
of Alpha), then the cast will throw a std::bad_cast exception.
In other words, dynamic_cast behaves like Java typecasts. We just call it
std::bad_cast instead of java.lang.ClassCastException.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Nicolas Alvarez wrote:
> GNU libc (not libstdc++!) has C functions to get backtraces at any moment.
> It's a GNU extension. You may very well call it in an exception handler.
>
> http://www.gnu.org/software/libtool/manual/libc/Backtraces.html
It would seem that's rather not very useful in the exception handler? Or am
I misunderstanding? If I catch a division-by-zero in main() and I want to
log what function that happened in, how would I do that?
I guess what I'm asking is, isn't it the case that by the time you're in the
exception handler, the stack frames leading to the unexpected exception have
already been cleaned up, and all the stuff that's on the stack is working
correctly?
If I have a server, and I want to catch and log failures, in most languages
I do something along the lines of
main() {
try {
do_main_loop();
} except Exception e {
log("Uncaught exception", e);
} finally {
clean_up();
}
}
but by the time I get to the log() call, the stack is gone, yes? Where would
I put the call to "backtrace" such that I'd catch the actual function that
threw the exception?
--
Darren New, San Diego CA, USA (PST)
My fortune cookie said, "You will soon be
unable to read this, even at arm's length."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
> Nicolas Alvarez wrote:
>> GNU libc (not libstdc++!) has C functions to get backtraces at any
>> moment. It's a GNU extension. You may very well call it in an exception
>> handler.
>>
>> http://www.gnu.org/software/libtool/manual/libc/Backtraces.html
>
> It would seem that's rather not very useful in the exception handler? Or
> am I misunderstanding? If I catch a division-by-zero in main() and I want
> to log what function that happened in, how would I do that?
Uh... Actually you're right :)
I dunno... I think you might be able to do something like this:
template<typename E>
void my_throw_exception(E& exc) {
//do the backtrace() dance and store the results somewhere in exc
throw exc;
}
But that's a bit cumbersome.
(PS: Division by zero doesn't throw a C++ exception)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On Mon, 09 Mar 2009 00:33:32 +0100, Nicolas Alvarez
<nic### [at] gmail com> wrote:
>
> void foo(Alpha* ptr) {
> Beta* beta = dynamic_cast<Beta*>(ptr);
> }
>
> If ptr is a Beta object that was (maybe implicitly) cast to a Alpha*,
> then
> beta is now equal to ptr (except its type is Beta*, so you can use Beta
> members). If ptr actually pointed to an Alpha, or a Delta (another
> subclass
> of Alpha), then the cast will throw a std::bad_cast exception.
No. A failed dynamic_cast of a pointer simply returns a null pointer. Only
failed casts of a reference result in a std::bad_cast exception.
--
FE
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
"Fredrik Eriksson" <fe79}--at--{yahoo}--dot--{com> wrote:
> No. A failed dynamic_cast of a pointer simply returns a null pointer. Only
> failed casts of a reference result in a std::bad_cast exception.
Thanks for that. I first thought it returned null, but then I searched the
Internets and saw a try { ... } catch(std::bad_cast), so I thought I was
wrong. I didn't notice the difference was that the example I found used
references :)
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |