puzzles with abort() and assert()

D

David

I am compiling C++ under both MacOsX and under Bloodshed Dev C++ on
Windows XP. Because the console window disappears under Bloodshed when
using the standard assert() via
#include <cassert>
I wrote my own "asserting.h", which goes as follows:
=============================================
#include <iostream>
#include <cstdlib>
#define asserting(e) \
if (!(e)) {\
std::cout << " assertion " << #e << " fails" << endl \
<< "File:" << __FILE__ << " line: " << __LINE__ << endl \
<< " aborting " << endl;\
getchar();\
abort();\
}//getchar() stops the console window disappearing before it can be
read
==============================================
This works partially, but it doesn't core dump when compiled with a
main statement asserting(0==1). Compiled with g++ -Wall -pedantic
-ansi. More precisely, I looked for a file with "core" as part of its
name, and couldn't find one. Does core dumping happen only if one
compiles with a debug flag? There seem to be many alternative debug
flags and I can't understand the manual explaining them. Which debug
flag should be used? Why does the standard assert.h define two macros
assert and __assert? What does one gain by this complication?
Suggestions for improvements to my code welcomed.
 
W

wittempj

Core dumping only happens on Unix based systems(like (OS X), not on
Windows - there you get a blue screen or a messagebox (depending on the
version you're running)
 
S

Sandeep

Sincere Suggestion ... Use a function instead of a Macro.(Specially if
it is such a _big_ macro!) C++ also has "inline" functions which are
far _better_ option than macros.
 
K

Kaz Kylheku

David said:
I am compiling C++ under both MacOsX and under Bloodshed Dev C++ on
Windows XP. Because the console window disappears under Bloodshed when
using the standard assert() via
#include <cassert>
I wrote my own "asserting.h", which goes as follows:
=============================================
#include <iostream>
#include <cstdlib>
#define asserting(e) \
if (!(e)) {\
std::cout << " assertion " << #e << " fails" << endl \
<< "File:" << __FILE__ << " line: " << __LINE__ << endl \
<< " aborting " << endl;\
getchar();\
abort();\
}//getchar() stops the console window disappearing before it can be

That's pretty nasty code bloat!!! Here is a much better idea:

extern void noninline_assert(const char *expr, const char *file, int
line);

inline void inline_assert(const char *expr, bool result, const char
*file, int line)
{
if (!result)
noninline_assert(expr, file, line);
}

#define my_assert(expr) inline_assert(#expr, (expr), __FILE__,
__LINE__)

Now, the asserts generate much smaller inline code. Moreover, the
compiler can decide to not inline the inline_assert() calls based on
its configuration options, code size or whatever.

Perhaps more importantly, you can change the definition of
noninline_assert without recompiling every source file that contains an
assertion.

You are more likely to decide in favor of keeping the assertions in
production code (a good idea!) if they are implemented with as little
overhead as possible.
==============================================
This works partially, but it doesn't core dump when compiled with a
main statement asserting(0==1). Compiled with g++ -Wall -pedantic
-ansi. More precisely, I looked for a file with "core" as part of its
name, and couldn't find one. Does core dumping happen only if one

Is this just under MacOSX, or are you actually looking for a core file
under XP???

Does the XP kernel even have the concept of a core dump?

What happens under Microsoft windows is that when a process suffers an
unhandled Win32 exception, a registered debugger application is
launched which can attach to that process. The application can extract
information about it: threads, stacks, memory, whatever.

If there is any core dumping going to be done, it will be by that
debugger application.

Microsoft's Dev Studio can play that role. A program called Dr. Watson
is also used; it's a kind of poor man's core dump which produces a text
file dump containing thread registers, stack backtraces, etc.
compiles with a debug flag?

That's an operating system question. Modern unixes have process limits:
attributes of a process, inherited by child processes from their
parents, which impose various resource limitations, such as maximum run
time, maximum virtual memory size, maximum core file size.

It may be that the default maximum core file size on your system is set
to zero as a soft limit, but a hard limit allows it to be increased
with a special command. That command is built into the shell, because
its effect has to be passed to a child process, and so it has to modify
the shell process itself. Just like 'cd' or environment variable
setting. In the GNU Bourne-Again Shell, it's called "ulimit"; "ulimit
-c <size>" sets up the core file size; you can get help on this builtin
by typing "help ulimit".
 
D

David

The reason I used a macro rather than a function was in order to get
the variables __FILE__ and __LINE__ correct. The compiler has the right
to treat any inline function as an ordinary function. __LINE__ will not
be handled as I want it to be in that case-----the function will return
the line number where the original function is defined.

Another contributor (Kaz Kyleku) has produced an approach that uses a
function (mostly), as you suggest, and, nevertheless gives the correct
filename and line number.

David
 
D

David

That's a very helpful response, which I find most enlightening. Thanks
so much.
David
 
G

Greg

Kaz said:
That's pretty nasty code bloat!!! Here is a much better idea:

extern void noninline_assert(const char *expr, const char *file, int
line);

inline void inline_assert(const char *expr, bool result, const char
*file, int line)
{
if (!result)
noninline_assert(expr, file, line);
}

#define my_assert(expr) inline_assert(#expr, (expr), __FILE__,
__LINE__)

Now, the asserts generate much smaller inline code. Moreover, the
compiler can decide to not inline the inline_assert() calls based on
its configuration options, code size or whatever.

Perhaps more importantly, you can change the definition of
noninline_assert without recompiling every source file that contains an
assertion.

You are more likely to decide in favor of keeping the assertions in
production code (a good idea!) if they are implemented with as little
overhead as possible.

I would hope not. Asserts are strictly a debugging aid. The time for
debugging is before the product is released. Enlisting one's users to
debug your program without their knowledge or consent is a shoddy
practice. After all what good does an assertion failure do for the
user? The program has failed and that is all that the user is going to
care about.

Moreover, using the standard assert macro ensures that asserts can be
safely disabled in production code (usually expanding to (void(0)) ).

Greg
 
K

Kai-Uwe Bux

Greg said:
Kaz Kylheku wrote: [snip]
You are more likely to decide in favor of keeping the assertions in
production code (a good idea!) if they are implemented with as little
overhead as possible.

I would hope not. Asserts are strictly a debugging aid. The time for
debugging is before the product is released. Enlisting one's users to
debug your program without their knowledge or consent is a shoddy
practice. After all what good does an assertion failure do for the
user? The program has failed and that is all that the user is going to
care about.

Not true. As a user I also care that bugs are fixed. Thus, I want to
be able to submit bug reports that point to the problem. For instance,
I grew to like the way gcc crashes on me:

gcc-3.4.0-killer.cc: In function `int main()':
gcc-3.4.0-killer.cc:15: internal compiler error: in c_expand_expr, at
c-common.c :4138
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.

In my experience, bugs reported this way are fixed rather quickly. And as I
said, that is something I care about.


Best

Kai-Uwe Bux
 
S

Sandeep

Not true. As a user I also care that bugs are fixed. Thus, I want to
Slightly Off topic:
The term 'user' can be interpreted in several ways. It can be a
developer, a tester, an enduser, a support person, and many other
'actors' for a software. While ensuring that there is a good mechanism
to report back the bugs in a software, you should remember not to go
overboard with the kind of technical details that you show to the
end-user. An end user is not interested in knowing how gcc crashed. You
can keep a log file which you can ask the user to upload. This will be
passed to the developers or QA people in the organization if the
support is unable to resolve the issue.
A software is for end-users ease and he should be transparent to the
technical glitches and should have a good "user experience". You should
read some articles on user interface design. and by this i do not mean
only "gui" design.
 
K

Kai-Uwe Bux

Sandeep said:
Slightly Off topic:
The term 'user' can be interpreted in several ways. It can be a
developer, a tester, an enduser, a support person, and many other
'actors' for a software.

Ok. I am an enduser of gcc.
While ensuring that there is a good mechanism
to report back the bugs in a software, you should remember not to go
overboard with the kind of technical details that you show to the
end-user. An end user is not interested in knowing how gcc crashed. You
can keep a log file which you can ask the user to upload. This will be
passed to the developers or QA people in the organization if the
support is unable to resolve the issue.
A software is for end-users ease and he should be transparent to the
technical glitches and should have a good "user experience". You should
read some articles on user interface design. and by this i do not mean
only "gui" design.

No, I should not read those: recall that I am an enduser of gcc. Instead,
people who write those should take my user experience into account.

I am just saying that I am very happy with the way gcc handles the reporting
problem. Also, I would be very suspicious of any file that I am supposed to
upload somewhere (maybe to the web site of some company) if I did not
understand its contents -- as an end user in this day and age, I am
paranoid about my privacy. Thus, I want to know which information I am
giving away.



Best

Kai-Uwe Bux
 
S

Sandeep

No, I should not read those: recall that I am an enduser of gcc. Instead,
73 75 69 74 20 79 6F 75 72 73 65 6C 66 2E 20
 
D

David

Greg says:
An even better idea would be to include <assert.h> and use then use the assert macro.

I did of course try this, but it failed.
As I said in my first post, the standard assert.h doesn't work for
Bloodshed Dev C++ (but perhaps I just don't understand Windows). On a
Windows console application, a window is opened for output from cout
and cerr. Using the standard assert from the standard assert.h causes
this window to disappear before one can read it. So the standard
assert.h is completely useless in this context. That's exactly why I
spent time and effort on writing my own version.

Perhaps I could open a command window in Windows XP, and run the
application from there, and then the window probably wouldn't go away
exactly when it's needed. This also means throwing out some of the
advantages of developing code under the Bloodshed IDE.

Can anyone tell me a way of using the standard assert.h in a way that
will actually work (preferably within the IDE)? I agree with Greg that
that would be the best solution, but does it exist?
David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top