is C++ worth it ?

J

James Kanze

Stuart skrev 2012-07-30 19:32:
The language standard cannot require a stacktrace without first
requiring that ALL implementations must use a stack. That would be
limiting, and exclude some of the platforms that were available when the
first C and C++ standards were written. ISO standards strive for a
consensus, which is hard if some manufacturers are excluded.

In the sense that you use the word here, C++ does require a
stack. It requires that you can return from a function, and
refind the environment that you left. However the
implementation does this, it can provide a backtrace. (Since
throwing an exception requires stack unwinding, an
implementation is required to have code which can do this.)
 
S

Stuart

This error is unique to MS compilers I think (and I think it's
optional there). With g++ under Linux (and all other Unix
compilers, I think), and access violation results in a core
dump, which is far preferrable for most applications.

The reason C++ doesn't have backtraces in exceptions is that
that's not what exceptions are for. Exceptions are designed to
be caught, so any backtrace would be ignored. If you have a
programming error, you want to stop immediately (in most
applications, anyway). Violently, and with a backtrace. In the
core file, or its equivalent---your client can't do anything
with a backtrace, but he can send you a core dump, so that you
can do something. (And of course, if the core dump isn't in
your test cases, you're not testing sufficiently.)


I had the following scenario: Software for quality assurance, it
controls a measurement machine with cameras and stage. Measurements take
up to 8 hours, so the user should be able to abort measurements if he
sees that the measured object is not good enough.

I implemented the aborting of measurements by means of an exception, so
that the stack is neatly unwound and the cameras stop acquisition and
the stages will be powered off. With exceptions this is rather
comfortable, since I don't have to clutter my code with

Picture* picture = 0;
if (acquirePicture (&picture) == ERROR_CODE_SHOULD_STOP)
return ERROR_CODE_SHOULD_STOP;

but simply write

Picture* picture = acquirePicture ();

Now I have the problem that I am bound to the Windows platform
(drivers), so when I do something wrong and get an Access Violation,
I'll get an BAD_ACCESS exception. This is actually a good thing because
my application does not shut down without a pip, but the stack is
unwound and the measurement machine returns to a defined state (stages
stopped, camera in idle mode). But unfortunately I have no more
information about where the Access Violation occurred since C++
exceptions are designed to be used in a different way. Well, this works
well for my StopException since I don't care which particalur action has
been performed when the user aborted the measurement, but in case
something went wrong, I'd like to see what happened.

I ended up setting up my own stack that can be examined later on, but
this is rather clumsy and requires all my actions to push themselves on
this stack (not too bad) and pop when they have finished. The later is
quite cumbersome since every code path where the action stops without an
exception has to ensure that the action pops itself from the stack, or
else my stack gets messed up.

A perfect language would generate an exception with a stacktrace upon an
Access Violation, which is much more preferable to a Core Dump. For
those who actually want to have the core dump, the language should
generate such a dump when the exception is not caught (AFAIK, Win32 does
not offer a setting that generates dumps upon Access Violations).

Thanks in advance,
Stuart

PS: @Jorgen: Come on, you may not know every little bit of the language
(who does), but certainly you know a LOT more than the average C++
programmer. I tend to read most of your posts because changes are good
that I can learn something new.
@James: The same goes for you.
 
N

Nick Keighley

Sadly, the answer to this question is yes.

If you are working in the industry, there is hardly a way around C++.
First of all, most drivers are provided with a C interface, which makes
C++ a "natural" choice. Besides this, hardware independence is mostly a
minor issue since the hardware asset of a large company won't be changed
overnight to a different platform, and for GUI related stuff there are
still platform independent libraries out there.

Curiously, the answer won't be to use Java or C#, as they are supposed
to be more high-level languages. Those are good languages that can be
easily learned by the majority of programmers. Even after 12 years as
C++ programming, and delving into some more obscure parts of template
programming, not even I would consider myself an expert on C++ (I think
Victor is one, and James).

Probably the flat learning curve that is what makes Java and C# so
popular. What the software industry needs is a language that can be used
suffiently well by the average programmer. I know that this sounds
contemptuous, but I know a lot of small companies that employ
Quereinsteigers (didn't find a proper English word for it, there is
probably none).

http://www.dw.de/dw/article/0,,6616141,00.html

learn a quirky German word each week...
 
N

Nobody

You mean unlike other languages, where an innocent looking function f(x)
can call other functions 10 levels deep?

In other languages, there will at least be an explicit function call.

In C++, copy constructors, destructors, and conversion operators can all
insert "invisible" function calls.
 
B

BGB

technically, an access violation results in a signal, which if
not caught by the application will terminate the application with
a core file (if the core file resource limit allows, and if the
stupid Fedora ABRT package isn't running).

yeah, and nifty stuff can be done in signal handlers, potentially
including, among other things, triggering an exception to the thrown and
the stack to be unwound. whether or not this is a good idea is a
separate issue, normal C++ exceptions may not necessarily work (a custom
mechanism may be needed), and have not yet determined how portable or
versatile this is.

though, granted, some of this could be determined by testing it.
 
D

Dombo

Op 31-Jul-12 9:26, Stuart schreef:
I had the following scenario: Software for quality assurance, it
controls a measurement machine with cameras and stage. Measurements take
up to 8 hours, so the user should be able to abort measurements if he
sees that the measured object is not good enough.

I implemented the aborting of measurements by means of an exception, so
that the stack is neatly unwound and the cameras stop acquisition and
the stages will be powered off. With exceptions this is rather
comfortable, since I don't have to clutter my code with

Picture* picture = 0;
if (acquirePicture (&picture) == ERROR_CODE_SHOULD_STOP)
return ERROR_CODE_SHOULD_STOP;

but simply write

Picture* picture = acquirePicture ();

Now I have the problem that I am bound to the Windows platform
(drivers), so when I do something wrong and get an Access Violation,
I'll get an BAD_ACCESS exception. This is actually a good thing because
my application does not shut down without a pip, but the stack is
unwound and the measurement machine returns to a defined state (stages
stopped, camera in idle mode). But unfortunately I have no more
information about where the Access Violation occurred since C++
exceptions are designed to be used in a different way. Well, this works
well for my StopException since I don't care which particalur action has
been performed when the user aborted the measurement, but in case
something went wrong, I'd like to see what happened.

I ended up setting up my own stack that can be examined later on, but
this is rather clumsy and requires all my actions to push themselves on
this stack (not too bad) and pop when they have finished. The later is
quite cumbersome since every code path where the action stops without an
exception has to ensure that the action pops itself from the stack, or
else my stack gets messed up.

Maintaining your own stack isn't necessary on the Windows platform. On
Windows you have the option to capture the structured exception (is not
the same as a C++ exception) when things like an access violation
occurs. At the point the handler is invoked the stack is still there to
be examined. Windows also provides functions to walk the call stack.
Many years ago I created a library for one of my clients to pinpoint
where in the code their software had crashed (which in spite of
extensive testing typically happened at some important client at the
other side of the world with very few if any clues on how to reproduce
the problem). This library installed a handler for structured exceptions
and uncaught C++ exceptions, and logs the point in the code exactly
where the exception originated from and the call stack at that point. It
also triggered flushing the trace buffers, collecting some other
information diagnostic information and put all of this in a .zip file,
pop-up a dialog instructing how to proceed and terminate the
application. The nice thing about this approach is that the existing
code (about 2+ million lines) didn't need to be changed.

Of course this library relied heavily on Windows specific calls. However
requiring this as part of the C++ standard would reduce the number of
platforms on which C++ can be used.
 
8

88888 Dihedral

BGBæ–¼ 2012å¹´8月1日星期三UTC+8上åˆ3時12分11秒寫é“:
yeah, and nifty stuff can be done in signal handlers, potentially

including, among other things, triggering an exception to the thrown and

the stack to be unwound. whether or not this is a good idea is a

separate issue, normal C++ exceptions may not necessarily work (a custom

mechanism may be needed), and have not yet determined how portable or

versatile this is.



though, granted, some of this could be determined by testing it.

Well, I have checked the size of C++ compiler from time to time.

It is always getting fatter and fatter. I think a slim JVM with the linux
in the mobile phone systems is attracting more people to work on "new"
software on mobile phones every day.
 
J

Jorgen Grahn

Nobody wrote 2012-07-31 15:59:

So you mean that when you see matrix_add(x, y) you immediately see how
much code that produces, while x + y is a mystery?

Perhaps he's just presenting this very common complaint from people
who dislike C++, and who's own favorite language doesn't have operator
overloading.
I don't get it!

Me neither, but as you know people who don't use C++ have been
complaining about this for ~30 years.

/Jorgen
 
B

BGB

I tend to use siglongjmp() to unwind when I catch asynchronous signals
such as SIGTERM/SIGINT/SIGQUIT. When catching synchronous, such as SIGSEGV, there are
no assurances that the rest of the program is still sane, and attempting
to generate a C++ exception may result in undefined behaviour.

yeah. another issue though is that given how signals and C++ exceptions
work on Linux, I would suspect (untested) that trying to throw a C++
exception in a signal handler could very well cause it to blow up.

but, yeah, siglongjmp() is probably a much better idea.
 
S

Stuart

Stuart said:
You can do that by defining your own handler (see _set_se_translator()) and
studying the SEH exception codes and addresses etc. Note that this must be
called in each thread in a multithreaded app.
You can do that too, by calling MiniDumpWriteDump() from your SEH exception
handler. A minidump file can be loaded in Visual Studio later or elsewhere
and the stack backtrace examined. On the positive side it is much smaller
than Linux core dumps; on the negative side it is not generated
automatically and setting the system up is not very trivial.

Didn't know this. Thanks for sharing.
This is all off-topic for general C++ of course.

That's what I was whining about. In my opinion this should be a C++
topic, but apparently I'm in the minority.

Thanks,
Stuart
 
M

Mark

Nobody wrote 2012-07-31 15:59:

So you mean that when you see matrix_add(x, y) you immediately see how
much code that produces, while x + y is a mystery?

I don't get it!

Both cases could result in a lot of extra code. However, for people
not familiar with C++, "x + y" looks like a simple expression.
 
M

Mark

yeah. another issue though is that given how signals and C++ exceptions
work on Linux, I would suspect (untested) that trying to throw a C++
exception in a signal handler could very well cause it to blow up.

but, yeah, siglongjmp() is probably a much better idea.

I often assume that if we receive a SIGTERM/SIGINT/SIGQUIT signal then
this is a request to terminate so the application would normally clean
up and quit.

With SIGSEGV I print out a stack trace and then allow the application
to create a core dump.
 
N

Nick Keighley

You can do that by defining your own handler (see _set_se_translator()) and
studying the SEH exception codes and addresses etc. Note that this must be
called in each thread in a multithreaded app.


You can do that too, by calling MiniDumpWriteDump() from your SEH exception
handler. A minidump file can be loaded in Visual Studio later or elsewhere
and the stack backtrace examined. On the positive side it is much smaller
than Linux core dumps; on the negative side it is not generated
automatically and setting the system up is not very trivial.

but not very hard either. And fairly well documented.
 
N

none

Both cases could result in a lot of extra code. However, for people
not familiar with C++, "x + y" looks like a simple expression.

Hmm... if one is so "unfamiliar" with the language that he doesn't
even know about operator overloading then really one should not read
the code and worry about how mouch code is execute when one line of
source code is read. It's not as if C++ was the only language
offering operatior overloading. Of course if the only language one
has ever been exposed to is Java, one might find C++ operator
overloading a novel concept.

Operator overloading can have two effect:
A) Improve the code base and make it more readable and more
maintainable.
B) Obfuscate the code base and make it less maintainable.

The difference between A) and B) is good programmers vs crap
programmers. C++ philosophy is to give good programmers the tools to
write better programs. Protection against B) is not built in the
language.

The typical criticism against operator overloading is overuse of it
for non-natural purpose but such a criticism can apply equally to
badly named functions.

Yannick
 
N

Nobody

So you mean that when you see matrix_add(x, y) you immediately see how
much code that produces, while x + y is a mystery?

No. The former involves an unknown amount of code in any language. In
C++, the latter also involves an unknown amount of code (and that code
isn't limited to the definition of operator+, as copy or conversion
operators may be invoked before operator+ is called).

Operator overloading is the least of the issues; many languages allow
functions to have non-alphanumeric names. It's the constructors,
destructors, and conversion operators which are the main pitfall.
 
B

BGB

If, for example, the SIGSEGV was because the FILE structure for stdout
had been stepped on (or the stdout OutputStream), then attempting to print
the stack trace will also fault - likewise, if you're using the glibc
backtrace helpers, they could also encounter undefined behavior after
a SIGSEGV/SIGBUS. You could use write(2, buf, strlen(buf)) to avoid
a subsequent signal in the stdio code, but the backtrace helpers may
still encounter issues if the stack got stepped on.

even this may not necessarily be unworkable, depending on how the logic
is set up. carefully written logic can still operate in the case of
bad/uncertain pointers. IOW: don't access memory through a pointer
unless it is (presumably) already known to be valid, ...

whether or not this is practical is a different matter (usually, it is
limited to special logic where the possibility of corrupted memory is
not unexpected, such as in the internals of a memory manager, ...).


more often though, the reason a person might be catching a SIGSEGV or
similar might actually be because a failure is expected in a certain
context, say:
potentiallyUnsafeOperation()
{
setup special signal handler;
do unsafe operation;
restore signal handler.
}

usually, in such a case, a person will know why the SIGSEGV or similar
has taken place, and so the intention is to trap and handle it.

in other cases, it might be because, actually, something "clever" is
being done with a memory region, so the signal handler may be used as a
way to handle it (I am aware of people doing this sort of thing partly
for reasons of implementing shared-memory and persistent memory systems,
among other things).

a big reason for not doing this though in the general case (such as
trying to use signal catching in an attempt to make a "crash-proof"
app), it that it may impede the ability to effectively debug the app
(and, may also just create an app that basically just goes into an
endless crash/recovery loop and is unable to resume normal operation
anyways).
 
J

James Kanze

On July 30, 2012 Stuart wrote:
[...]
Now I have the problem that I am bound to the Windows platform
(drivers), so when I do something wrong and get an Access Violation,
I'll get an BAD_ACCESS exception. This is actually a good thing because
my application does not shut down without a pip, but the stack is
unwound and the measurement machine returns to a defined state (stages
stopped, camera in idle mode). But unfortunately I have no more
information about where the Access Violation occurred since C++
exceptions are designed to be used in a different way. Well, this works
well for my StopException since I don't care which particalur action has
been performed when the user aborted the measurement, but in case
something went wrong, I'd like to see what happened.

That's a problem regarding the platform, *not* C++. The last
thing you want in such cases is for the stack to be unwound.
You want a dump of the state exactly where the error occurred.
A core dump, under Unix. (From what I understand, it's possible
to configure Windows to behave correctly as well.)

[...]
A perfect language would generate an exception with a stacktrace upon an
Access Violation, which is much more preferable to a Core Dump. For
those who actually want to have the core dump, the language should
generate such a dump when the exception is not caught (AFAIK, Win32 does
not offer a setting that generates dumps upon Access Violations).

How is unwinding the stack preferrable to a core dump. The
stack trace tells where you were, but doesn't offer any
possiblity to see the surrounding state at each level.
Unwinding the stack looses important information.

(Where I work, when we have such problems, the first step is to
recreate them in the Unix environment, where we can get a core
dump, with all of the essential information.)
 
J

James Kanze

On 7/31/2012 9:20 AM, Scott Lurndal wrote:
[...]
yeah, and nifty stuff can be done in signal handlers, potentially
including, among other things, triggering an exception to the thrown and
the stack to be unwound. whether or not this is a good idea is a
separate issue, normal C++ exceptions may not necessarily work (a custom
mechanism may be needed), and have not yet determined how portable or
versatile this is.

You cannot throw in a signal handler. The results are undefined
behavior. And it doesn't reliably work on any platform I know.
though, granted, some of this could be determined by testing it.

Testing won't give you many answers here. Throwing in a signal
handler is undefined behavior. It may work in your tests, but
not in any real application.
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top