Article on possible improvements to C++

D

dragan

Alf said:
* dragan:

It sounds as if you degree with my description.

Obviously (but too, not afraid to "be stupid")
In that case, sorry
but whatever you mean is incorrect.

Sure it is, but you had to say that BEFORE you proved it, huh.
Placement new does exactly the
same as non-placement new: calling an allocation function

In practice (MY practice), it does no allocation. Don't bore me with your
laws please Mr.

Go find another corner to place a camera on to control your offspring.
with
specified allocation function arguments, and if that succeeds,
calling a constructor with specified constructor arguments.

Maybe I don't care? Meaning, maybe I don't care to recognize that subtlety?
Cheers & hth.,

- Alf

Siglines are so yesterday. Stop wasting bandwidth for self-serving purposes.
I don't trust anyone with a sigline.
 
S

sfuerst

From the article:

"With explicit construction, the zero-argument count, and no-return-value
requirements for a constructor evaporate."

What about compiler-generated temporaries created via a constructor? You
pre-supposed only one pattern of construction: that in which the developer
is writing code. There is not just one pattern of construction to address..

doh... forgot about those.

Ok - there are three types of temporaries. (Correct me if I'm wrong.)

The first are implicit conversion constructors, and the second are
copy constructors used for things like function arguments.

Implicit conversion is seen as problematic these days. (It breaks the
type-safety) So it probably can be depreciated in favor of explicit
conversion instead.

Function arguments are a different story. I suppose one way to remove
implicit copy constructors is to change the default to pass-by-
reference for classes. This is probably a bit too much of a change,
however. Perhaps a nicer solution exists. :)

Finally, you get temporaries in expressions involving operator
overloading. I'll ignore those... since you are going to have to wrap
the expression in a catch statement anyway if the type is so complex
that its constructor could throw an exception.

Steven
 
S

sfuerst

From the article: "Why not use this difference between plain-old-data and
more complex objects to define the difference between structs and classes?"

Bjarne and his peers wrestled with that (and probably argued about it a lot
too) when C++ was first designed. Bjarne notes in his book "The Design and
Evolution of C++" (which you should read or read again because you seem to
be oblivious to what was written in that tome) that he thought if he would
have created such a distinction (that is, ANY significant distinction)
between structs and classes that C++ would have been "stillborn". We'll
never know what would have been had structs and classes been fundamentally
different, but the reason why structs and classes are defined as they are is
well-documented.

Bjarne had different constraints than the ones I was working with.
Bjarne required C backwards compatibility, whereas I am explicitly
dropping all backwards compatibility requirements. Bjarne also wanted
people to use his new language. I am under no delusions, and agree
that the chances of anyone making the suggested changes are extremely
small to non-existent. :)

The key problem is that C++ is too complex. However, there are
reasons it has all the features it does. You cannot just delete
features to reduce the complexity. The hard part is thinking of ways
to increase the orthogonality of the language to reduce complexity but
without removing any functionality. For example, I think the trick of
converting member function pointers into normal function pointers by
the magic thunks is pretty cool. You can use it to get rid of three
operators, and also simplify the ABI at the same time. (Not to
mention that those offending operators are a pain to use due to their
wrong precedence level... who likes adding all the extra brackets
required to use them?)

Steven
 
S

sfuerst

sfuerst said:
Hello, I've written an article athttp://locklessinc.com/articles/10_problems_with_c++/ [SNIP]
Any comments, or flames are welcome. :)

Your captcha at the web does not work, so I have to put here my comment:

Oops, sorry. The cgi script didn't like the "++" in the url. I've
hacked around that now, but the main page now ends in "cpp/" instead
of "c++/".

Steven
 
P

Pavel

dragan said:
OK, I mis-comprehended your thought, probably because you used "10" instead
of "3".
I think you are referring to someone else's post (maybe OP's).
I don't have the data/information across a wide variety of software to
assess how important that is, BUT, I feel it's probably "a detail".
"Operator overloading is for numerics", to say a cliche.
Again, I am no way for operator overloading, it was not my post. I
actually would prefer them out of the language altogether (IMHO even
function overloading creates more issues that it solves problems). I was
responding to you response to Paavo: he complained about difficulties
with handling errors in operators and you seemed to have given
set_new_handler() as a counterexample; hence the objections.
Error handling code is usually not performance-critical, so it doesn't
matter.
Error handling is usually not performance-critical. Setting up for
catching an error has to be done every time no matter whether the error
actually occurs so it very well may be performance-critical. Just try to
start using set_new_handler() to report errors to different targets in
some pipeline- say, when message reader reads a message and memory
cannot be allocated, some higher level in message reader is to be
notified, but when this message is processed, a higher level at the
processor has to be notified. With exceptions, this happens
automatically (although not for free, either).

But actually I meant more design/coding/training/acceptance/maintenance
costs.
Performance-wise? Who cares? Mechanics-wise? A little bit of code that may
indeed help to focus on doing error handling rather than dispatching errors.
Quite a bit of code will you need to properly destroy automatic objects
(which is quite often the required part of "error handling". If handling
of an error does not require stepping way back, that error can be IMHO
renamed to "yet another condition arising at normal course of given
business").
If by "solution" you mean "one size fits all", there is no answer.
Totally agree, I was the first to say "for a significant share of
tasks". :)

Not
without concession anyway.
If you like exceptions, use them. I prefer to avoid them when/wherever
possible.
Essentially to me it sounds like: I prefer not to mistake business
requirements for errors. And I could not agree with your more if that's
what you mean. To me an error means: I can't continue this action. Now
what am I going to do? At this point, to have at least the second choice
(the first is to terminate the program and it does not require
exceptions), a robust context-switching mechanism is needed
(longjmp/setjmp, EPOC32/Symbian's "Leaves" with home-made cleanup stack
etc -- you name it). In most situations where the failed "action" is not
a separate "task" (whatever this means -- a thread, a process or
whatever -- in which case you could send a message to another task and
terminate the failed task), exceptions seem to be the most convenient
and least costly (in terms of programming/code maintenance) mechanism.

I don't do large-scale development and I have a toolbox full of
error-handling techniques. I never understood this quest for "one and only
one" when that is hardly ever appropriate: one error-management mechanism,
one "standard" library, one <your choice here>...
See above.. I am not sure about you definition of an error though.
Locally handle-able conditions (errors)
This is telling.. what is you definition of an error as opposed to any
other "locally handle-able" condition?
are much more numerous than global errors handle-able appropriately by a technique such as set_new_handler.
Again, how do you destroy C++ local objects with using a handler?
There has to be a number of approaches to error handling or else it is a
lame solution to the problem of error management, so I say. C++ exceptions
can replace those set_new_handler-like things. Sure, you can use them at the
local level too, but then with that comes all the confusion of when to just
crutch on the mechanics or think about the problem and handle the error, and
it's the whole "exceptional case botching up the common case" thing again.
The real sad thing about C++ exceptions is that it suppresses thought about
error handling in general and the science of error handling almost
stagnates, in C++ groups anyway.
People tend to misuse exceptions, that's true. But IMHO they misuse
other C++ features much more. For example they tend to misuse function
overloading. In particular operator overloads. As well as namespaces.
And passing by references. As well as name hiding. And especially
templates. And compile-time policies. And SFINAE. And recursive template
instatiations. Typelists in particular. And compiler time in general.
And even old poor preprocessor. And what not. And did I mention operator
overloading yet? Of the above misuses, misusing exceptions looks a
smaller sin to me.

-Pavel
 
D

dragan

Pavel said:
I think you are referring to someone else's post (maybe OP's).
Again, I am no way for operator overloading, it was not my post. I
actually would prefer them out of the language altogether (IMHO even
function overloading creates more issues that it solves problems). I
was responding to you response to Paavo: he complained about
difficulties with handling errors in operators and you seemed to have
given set_new_handler() as a counterexample; hence the objections.

Error handling is usually not performance-critical. Setting up for
catching an error has to be done every time no matter whether the
error actually occurs so it very well may be performance-critical.
Just try to start using set_new_handler() to report errors to
different targets in some pipeline- say, when message reader reads a
message and memory cannot be allocated, some higher level in message
reader is to be notified, but when this message is processed, a
higher level at the processor has to be notified. With exceptions,
this happens automatically (although not for free, either).

But actually I meant more
design/coding/training/acceptance/maintenance costs.

Quite a bit of code will you need to properly destroy automatic
objects (which is quite often the required part of "error handling".
If handling of an error does not require stepping way back, that
error can be IMHO renamed to "yet another condition arising at normal
course of given business").

Another simple answer from moi: RAII. Problem solved. RAII and exceptions
are orthogonal concepts. RAII works as good with other error handling
strategies as it does with exceptions.
Totally agree, I was the first to say "for a significant share of
tasks". :)

Not
Essentially to me it sounds like: I prefer not to mistake business
requirements for errors.

I just meant that I don't want to use the complex thing when another simple
thing will work just fine.
And I could not agree with your more if
that's what you mean. To me an error means: I can't continue this
action. Now what am I going to do? At this point, to have at least
the second choice (the first is to terminate the program and it does
not require exceptions),

Termination is only a choice in application code, not in library code. A
library has to propogate or handle the error. Maybe if a precondition is
violated you can make a case for termination from a library, not sure.
a robust context-switching mechanism is
needed (longjmp/setjmp, EPOC32/Symbian's "Leaves" with home-made
cleanup stack etc -- you name it).

I wouldn't call setjmp/longjmp a "context switching mechanism", but I know
what you meant. setjmp/longjmp is not an option in C++ because destructors
aren't called during "the unwinding" of the "call stack".
In most situations where the
failed "action" is not a separate "task" (whatever this means -- a
thread, a process or whatever -- in which case you could send a
message to another task and terminate the failed task),

Doesn't appear to be an option because that won't "unwind the stack".
exceptions
seem to be the most convenient and least costly (in terms of
programming/code maintenance) mechanism.

That's one way to do it, yes. I'm sure there are others, but that
necessarily commits you to using more than one EH thing.
I don't do large-scale development and I have a toolbox full of
See above.. I am not sure about you definition of an error though.

I'm not either, LOL! ;) I've never sat down and wrote a definition of what
an error is, but I agree with the general usage of the term as used in any
of a number of books. But then again, errors are application-specific too
and categorizing and defining and handling them is application-specific then
also.
This is telling.. what is you definition of an error as opposed to any
other "locally handle-able" condition?

I don't want to get into a glossary debate.
Again, how do you destroy C++ local objects with using a handler?

Well, perhaps you can resume after the handler runs if that is how your
handler system works. If still no go, RAII time to do it's thing. How you
setup functions to do cleanup is a stylistic preference. A few macros and a
goto macro perhaps.
People tend to misuse exceptions, that's true. But IMHO they misuse
other C++ features much more. For example they tend to misuse function
overloading. In particular operator overloads. As well as namespaces.
And passing by references. As well as name hiding. And especially
templates. And compile-time policies. And SFINAE. And recursive
template instatiations. Typelists in particular. And compiler time in
general. And even old poor preprocessor. And what not. And did I
mention operator overloading yet? Of the above misuses, misusing
exceptions looks a smaller sin to me.

I think error management is the most important and the hardest to get right.
It is both permeating and subsystem-ish whereas the other things are
detail-ish.
 
D

dragan

sfuerst said:
Bjarne had different constraints than the ones I was working with.
Bjarne required C backwards compatibility, whereas I am explicitly
dropping all backwards compatibility requirements. Bjarne also wanted
people to use his new language. I am under no delusions, and agree
that the chances of anyone making the suggested changes are extremely
small to non-existent. :)

You seem to be not on one side of the fence or the other: On one side, you
say "these changes should be made to C++"; On the other, you say "new
language based on C++". Which is it?
The key problem is that C++ is too complex.

As I noted though, that is by design rather than by error of omission or
similar. It's impossible to make C++ simple because then it wouldn't meet
the requirements for C++ so it wouldn't be C++ anymore. See what I mean?
However, there are
reasons it has all the features it does.

That's all I said.
You cannot just delete
features to reduce the complexity. The hard part is thinking of ways
to increase the orthogonality of the language to reduce complexity but
without removing any functionality.

Thay may have been "hard" back in the days of C++'s invention, but it's
quite just a gathering task today. Since you have in your article some
common knowledge and maybe presented as novel, I assume everything there is
nothing new. Finally, I don't see "the C++ community" as a place to make any
long term or sweeping changes (the long committee process, etc.): that's the
domain of new language development like Google is doing with Go.
 
P

paulto

dragan wrote:
[snipped]
Another simple answer from moi: RAII. Problem solved. RAII and exceptions
are orthogonal concepts. RAII works as good with other error handling
strategies as it does with exceptions.
RAII is a great idea but you need something to kick off the destructors.
It may be an important component of error handling strategy but
exception or something else is needed to actually kick off object
destruction if error processing requires changing the context outside of
normal flow control operation.
I just meant that I don't want to use the complex thing when another simple
thing will work just fine.
see below..
Termination is only a choice in application code, not in library code. A
library has to propogate or handle the error. Maybe if a precondition is
violated you can make a case for termination from a library, not sure.
see below...
I wouldn't call setjmp/longjmp a "context switching mechanism", but I know
what you meant. setjmp/longjmp is not an option in C++ because destructors
aren't called during "the unwinding" of the "call stack".
Exactly my point. It won't automatically, you will have to hand-craft
some stupid mechanism like EPOC32/Symbian cleanup stack and never forget
put your important objects on it. I am just saying: for error processing
some mechanism of context-switching is needed (BTW longjmp/setjmp is
context-switching: the context in this case are the registers including
instruction pointer or equivalent and stack frame pointers or
equivalents. In practice, it's not enough as you want application-level
"unwinding" of automatic objects as you change the stack pointers or
equivalents; that's why I am saying exceptions are convenient and cheap
without obvious drawbacks for the purpose (as long as you do not require
more flexibility in selection of error processing code targets than
exception give you), library-based cleanup-stack is worse and
longjms/setjmp is still worse.. )
Doesn't appear to be an option because that won't "unwind the stack".
If you terminate the process, the automatic objects are destroyed; if
the "task" is something else, you are right, it's on you again :).
That's again why I say exceptions are convenient.
That's one way to do it, yes. I'm sure there are others, but that
necessarily commits you to using more than one EH thing.
I mentioned few above; but don't know anything as convenient as exceptions.
I'm not either, LOL! ;) I've never sat down and wrote a definition of what
an error is, but I agree with the general usage of the term as used in any
of a number of books. But then again, errors are application-specific too
and categorizing and defining and handling them is application-specific then
also.


I don't want to get into a glossary debate.
I am not trying going there either; but we seem to be talking about
different things when we mention "error" term and this is not
productive. I would suggest to exclude A "locably-handleable" conditions
from the discussion. I do not see a reason for segregating them into a
separate category of "errors" from other application-level conditions;
you seem to argue exceptions is not the best way of processing them; I
do not challenge this at all, I just do not call these "business cases"
or "uses cases" "errors".
Well, perhaps you can resume after the handler runs if that is how your
handler system works.
See above paragraph this time :).
> If still no go, RAII time to do it's thing.
So, how do you kick-off the destructors for objects you initialized
under RAII paradigm?
> How you
setup functions to do cleanup is a stylistic preference. A few macros and a
goto macro perhaps.
goto is local withing the function, right? You can call these situations
"locally-handleable errors", too, if you like but they IMHO do not
require macros (no more than other business logic, that is). If your
desired control point is few call stacks up, goto can't help you and
this is a distinctive characteristic of an error to me.

I think error management is the most important and the hardest to get right.
It is both permeating and subsystem-ish whereas the other things are
detail-ish.
It definitely is if you do not limit the scope of your effort first.
"Fixing the world" is rarely productive enterprise. So, the clear
definition of what is and, most importantly, what is not an error, is in
order as well as some definition of what you would expect from error
management.

-Pavel
 
I

Ian Collins

paulto said:
dragan wrote:
[snipped]
Another simple answer from moi: RAII. Problem solved. RAII and exceptions
are orthogonal concepts. RAII works as good with other error handling
strategies as it does with exceptions.
RAII is a great idea but you need something to kick off the destructors.
It may be an important component of error handling strategy but
exception or something else is needed to actually kick off object
destruction if error processing requires changing the context outside of
normal flow control operation.

That's exactly what RAII does for you. You manage resources so they
will be freed when the managing object goes out of scope.
 
P

Pavel

Ian said:
paulto said:
dragan wrote:
[snipped]
Quite a bit of code will you need to properly destroy automatic
objects (which is quite often the required part of "error handling".
If handling of an error does not require stepping way back, that
error can be IMHO renamed to "yet another condition arising at normal
course of given business").

Another simple answer from moi: RAII. Problem solved. RAII and
exceptions
are orthogonal concepts. RAII works as good with other error handling
strategies as it does with exceptions.
RAII is a great idea but you need something to kick off the
destructors. It may be an important component of error handling
strategy but exception or something else is needed to actually kick
off object destruction if error processing requires changing the
context outside of normal flow control operation.

That's exactly what RAII does for you. You manage resources so they will
be freed when the managing object goes out of scope.
How do you make the language to realize the object is going out of scope
if you do not use exceptions? The discussion is about using exceptions
vs alternative error-processing techniques. As dragan correctly points
out, RAII is an orthogonal concept to the method of dispatching the
control point to the desired spot in the code (the concept that works
with exceptions quite nicely, BTW as many orthogonal concepts do). I am
not quite sure though why he mentioned it at all -- it only makes the
point in favor of exceptions as it seems to me.

-Pavel
 
D

dragan

paulto said:
dragan wrote:
[snipped]
Another simple answer from moi: RAII. Problem solved. RAII and
exceptions are orthogonal concepts. RAII works as good with other
error handling strategies as it does with exceptions.
RAII is a great idea but you need something to kick off the
destructors. It may be an important component of error handling
strategy but exception or something else is needed to actually kick off
object
destruction if error processing requires changing the context outside
of normal flow control operation.

Not really. Local objects will have their destructors called when they go
out of scope. That has nothing to do with exceptions, PER SE. Yes, if you
create a C++ exception mechanism, then you must, in turn, create a new way
for destructor calling. Otherwise though, destructors get called when the
object goes out of scope.

Is there a reason why there is so much pedantic and elementary discussion
necessary here? Personally, _I_ assume that everyone here knows everything
in anything ever written in a commonly available C++ book/programming book,
etc. Save for the "harder" stuff. While it is "fun" a little bit to "burn
things in" or "retrive data in the back of the mind", sometimes it appears
that some people in these language groups are just "chomping at the bit" for
an opportunity to recite common knowledge, at the expense of another maybe,
and for what? Is there some contest I don't know about? I felt the need to
"reprimand" and "take to the mat" the other guy for childish tactics for the
very same reason. This little passage is not to curb questions and thoughts
of those who trully don't know and seek to know: there is NO dumb question.
I mean, I remember when I didn't know everything and how it sucked so bad,
but I digress. :)

(Yes, when I say something that is incorrect, I'm just faking it: I really
do know. Yeah, that's the ticket!)
see below..

see below...

Exactly my point. It won't automatically, you will have to hand-craft
some stupid

Ah, now we are getting "real". You say "stupid" and you meant it
passionately. OK, noted. There's nothing wrong with passion and/or
personality (as if "boring" language newsgroups didn't need help in that
department). :p
mechanism like EPOC32/Symbian cleanup stack and never
forget put your important objects on it. I am just saying: for error
processing some mechanism of context-switching is needed (BTW
longjmp/setjmp is context-switching: the context in this case are the
registers including instruction pointer or equivalent and stack frame
pointers or equivalents.

I would and do reserve that terminology for the commonly known usage of it:
switching from user mode to kernel mode, and switching threads too.
In practice, it's not enough as you want
application-level "unwinding" of automatic objects as you change the
stack pointers or equivalents;

You don't have to do that if you aren't "setjmping/longjmping" or "C++
exceptioning": it happens just as in normal program flow. Destructors get
called when class objects go out of scope.
that's why I am saying exceptions are
convenient and cheap

You're are juxtaposing "cause and effect".
without obvious drawbacks for the purpose (as
long as you do not require more flexibility in selection of error
processing code targets than exception give you), library-based
cleanup-stack is worse and longjms/setjmp is still worse.. )

OK, this is turning into a tangent about "why you should use exceptions".
Save to say, you are "preaching to the choir". I don't want to age standing
still and this thread is becoming one of those rehashes of stuff everyone
already knows and makes their own choices about. Up next for sure: "why you
should use garbage collection". No offense, but I have better, more
things to do. Unless you have some "new said:
If you terminate the process, the automatic objects are destroyed;

While I don't not believe you, I don't believe you. I probably don't have to
know that either because:

1. It is probably platform-specific.
2. It's not a separate thing to design around the whole envelope of such
behavior.
if
the "task" is something else, you are right, it's on you again :).
That's again why I say exceptions are convenient.

"Convenience" is not even on the list of requirements though.
I mentioned few above; but don't know anything as convenient as
exceptions.

"I gotta go".
I am not trying going there either; but we seem to be talking about
different things when we mention "error" term and this is not
productive.

I didn't see that as hampering the elementary and pendantic dialog, but I do
agree that a reasonably agreed-upon glossary of terms is required for
efficient discussion or debate or problem resolution. I think TOO much time
is spent discussing different things ("talking past each other") in these
language groups for that very reason: everyone starts jabbering in their own
foreign English/Technolang. Which is fine if it is clear from the context,
else it is very wasteful.
I would suggest to exclude A "locably-handleable"
conditions from the discussion.

There is no more discussion unless you have something new (to the larger
scope of the body of knowledge that is this stuff) to present.
I do not see a reason for segregating
them into a separate category of "errors" from other
application-level conditions;

Well you ponder that some more if you want to. I consider classification of
errors an important step in error management. Without thought in that task,
I would assess the development process deficient. Nuff said. I'm not here to
talk about my development methods.
you seem to argue exceptions is not the best way of processing them;

"best" sounds very final. Don't you think? It's a good way. A car may be
"the best way" to go to work, but I still ride my bike sometimes. Go figure!
I
do not challenge this at all, I just do not call these "business
cases" or "uses cases" "errors".

I can't spend more time on this.
See above paragraph this time :).

So, how do you kick-off the destructors for objects you initialized
under RAII paradigm?

"kick off" what? There's nothing to "kick off", unless you are under the
impression that "unwind" is something tied to an exception mechanism. Do you
know what an exception is? Is it different from an "error"? How? Have you
considered that someone like maybe Google who "shuns C++ exceptions" may
not be using ANY other kind of exception either? What is an "exception"? I
believe that answer will answer your questions about "kicking off
destructors".
goto is local withing the function, right?
Yes.

You can call these
situations "locally-handleable errors", too, if you like but they
IMHO do not require macros (no more than other business logic, that is).

By now I'm "getting to know you", and "your take" on macros I'm sure can be
easily ascertained from "your take" on exceptions. No offense, but you are
repeating programming "cliches".
If your
desired control point is few call stacks up, goto can't help you and
this is a distinctive characteristic of an error to me.

So why are you talking at me about it? Thought + time = resolution.
It definitely is if you do not limit the scope of your effort first.
"Fixing the world" is rarely productive enterprise. So, the clear
definition of what is and, most importantly, what is not an error, is
in order as well as some definition of what you would expect from
error management.

"I don't know what an error is". I want you to tell me. Unfortunately, I
have an idea of how long that will take until you know and I can't wait that
long. Don't ever again try to suck me into an elementary/pendantic
discussion about this stuff, thanks. When you have something new to add to
the existing "body of knowledge", I'll probably be reading it.
 
D

dragan

Ian said:
paulto said:
dragan wrote:
[snipped]
Quite a bit of code will you need to properly destroy automatic
objects (which is quite often the required part of "error
handling". If handling of an error does not require stepping way
back, that error can be IMHO renamed to "yet another condition
arising at normal course of given business").

Another simple answer from moi: RAII. Problem solved. RAII and
exceptions are orthogonal concepts. RAII works as good with other
error handling strategies as it does with exceptions.
RAII is a great idea but you need something to kick off the
destructors. It may be an important component of error handling
strategy but exception or something else is needed to actually kick
off object destruction if error processing requires changing the
context outside of normal flow control operation.

That's exactly what RAII does for you. You manage resources so they
will be freed when the managing object goes out of scope.

That's all I had to say? I just spent a half hour replying to him. Twas time
well-spent though. I don't regret it at all. (OK, I do, but for selfish/time
reasons).
 
I

Ian Collins

dragan said:
Ian said:
paulto said:
dragan wrote:
[snipped]
Quite a bit of code will you need to properly destroy automatic
objects (which is quite often the required part of "error
handling". If handling of an error does not require stepping way
back, that error can be IMHO renamed to "yet another condition
arising at normal course of given business").
Another simple answer from moi: RAII. Problem solved. RAII and
exceptions are orthogonal concepts. RAII works as good with other
error handling strategies as it does with exceptions.
RAII is a great idea but you need something to kick off the
destructors. It may be an important component of error handling
strategy but exception or something else is needed to actually kick
off object destruction if error processing requires changing the
context outside of normal flow control operation.
That's exactly what RAII does for you. You manage resources so they
will be freed when the managing object goes out of scope.

That's all I had to say? I just spent a half hour replying to him. Twas time
well-spent though. I don't regret it at all. (OK, I do, but for selfish/time
reasons).

Sorry, that was bad form relying out of context.
 
N

Nick Keighley

you have an odd way of quoting that makes it hard to distinguish what
you are saying from what you are responding to.

"sfuerst" <[email protected]>

sfuerst:
I think you've missed the point.  In other languages, people are able
to globally override memory allocation.  This is done for debugging:
To find a memory leak, you can store the file and line of the
allocation call, and see where the allocations that are never freed
come from.  Another use is profiling: What sized allocations are your
program repeatedly allocating and freeing?  Perhaps the use of some
other allocator other than the default could improve performance.

With C++, you can use the placement new syntax to pass extra
information to an overridden new routine.  The problem is that there
is no way to globally cause this to happen, without manually editing
every single call to new in your program.


Balog Pal:
TMK there is a bunch of leak detectors out there.

but if I want to build one?

Balog Pal:
But I never used any of them -- Visual C++ has it built-in for decades.  And
all it takes a single #define new debug_new  at the front of the source..  If
you use it, then you get the source file/line of allocation besides the
leaked block address, size and content.

The last time I had to put together a [cheap?] diagnostic was around '94, even
then I was possibly just not aware of a ready solution...

Manually editing lines of code?

I've used perl scripts to do things like that


Balog Pal:
What you ask for, is sitteng there, working, discover how it is done instead
of claiming it impossible.

OTOH, the real way to make correct code is definitely not going by that info
but through using consistent RAII-like handling, and reviews enforcing it..

I keep on seeing things like this. How exactly does RAII deal with
allocations that don't follow a simple model?


Balog Pal:
As test runs will hardly cover all possible paths including errors and
exceptions, so relying on the empty leak list from a random run is nothing
but illusion of being okay.  While with trivial style it is easy to make
leaks impossible.

so explain to me how I trivially remove all possible memory leaks from
my programs.


Balog Pal:
Why invest in better patches instead of cure the problem at roots?

because you can't remove the problem at its root. If you want true
dynamic allocation then you need to trigger delete somehow. Unless you
add garbage collection to C++.

<snip>
 
N

Nick Keighley

sfuerst said:
sfuerst wrote:
Hello, I've written an article [...] detailing ten
perceived problems with C
You are right, basically you are stuck.  Exceptions are sometimes the
only way to communicate failure conditions in some cases.  [...]
the problem with exceptions is [...] that
they provide a poorly documented interface to functions.  In theory,
all functions should list what potential exceptions they could throw
as part of their definition / external documented interface.   [...]
 The reason is that far too many
exceptions are possible in any non-trivial code.  
[...]
For reducing the combinatorial explosion, all exceptions propagating out
of a library should be derived from std::exception.

which rules out using much of boost
In my experience, most exceptions finally get logged as a text, or
displayed to the end user as a text.

not in mine. many exceptions are swallowed silently. Even if they are
reported to a log file that isn't the primary reason for the
exception. Think automatic invocation of dtors and passing control
back up the stack.

So what I need is just to convert
every exception to text.

use what()

This can be done by a single function, which is
called from all catch(...) clauses (... is verbatim here!). The function
rethrows and catches the exception, converting it into the text
appropriately for all kind of known exception types (language translation
can be done at this point as well).

sounds complicated

Having special exception types only comes handy when they are used for
handling special situations near the throw point. But this should not be
visible to other libraries and should not cause combinatorial explosion.

define "near". What if I want to pack out of some deeply nested
transaction? The call can't proceed and all the associated resources
need to be freed- some of which are actually physical resources like
radio channels or comms links.
 
N

Nick Keighley

That's the wrong question to ask though because it pre-supposes exceptions.
The question is, "what are the alternatives?".

1. Don't write code that errors in constructors or operators.

what do I do if construction fails? There is no memory available.
There're aren't any working radio channels. That PDU won't parse.

2. Do default error handling instead of requiring propogation via
exceptions: exit(), perhaps.

you'd love that if your mobile phone worked that way...

"The entire mobile phone network crashed today when Tracey Smith to
tried to phone her boyfriend during her lunch break".

I think I'll go back to carrier pidgeons

3. Use another error handling technique.
4. ?

make constructors return a value and ban operator redefinition.

The argument for exceptions goes something like this: Some people want to
write code where errors can happen in constructors and operators,

no. We can't avoid construction sometimes failing. The physical layer
is imperfect.

therefore
exceptions were created. Because exceptions were created, why not just go
ahead and use them all over the place.

It's a classic case of the exceptional case (no pun intended, but a little
humourous anyway) botching up the common case.

exceptions make your code look much cleaner.
 
B

Balog Pal

Nick Keighley said:
you have an odd way of quoting that makes it hard to distinguish what
you are saying from what you are responding to.

A few messages are not getting quoted, even with OE-quotefix' help...
probably some headers confuse the system.

Like this one, it is correctly colored, but the text is elft as is, no >
inserted. Fortunately it is rare.
but if I want to build one?

Guess then you take all the pain of the redundant work... Should a language
be tuned for such activity in general?
I keep on seeing things like this. How exactly does RAII deal with
allocations that don't follow a simple model?

Insert some example of the model you think problematic.

so explain to me how I trivially remove all possible memory leaks from
my programs.

"Remove" is not the way. You start from nothing -- that is assumed
leak-free ;-) and add all the stuff in a way that can't leak. So your
program is always leak-free.

The style is like:
- 'delete' is forbidden in "client" code. It is privilige of the the few
library classes that serve as managers. Like auto_ptr.
- The result of every new goes immediately to one such manager.
That's about it. Certainly there are a few cases where ownership is
transferred -- so look what happens to result of release(), Detach() and
similar calls, that is IME natural.

Same thing applies to other resources: files, handles, GDI resources, locks,
transactions.

As an example, you may look some old Petzold examples to struggle with raw
WIN API in pure C -- and see how the same thing looks using MFC's CFont,
CBrush and similar wrappers. The difference is incredible in readability
and clearness. As a side effect DBWIN no longer explodes on any random
program reporting a zillion of lost resources.

If you want a very simple example, think a program that processes text
manipulating strings all its time. A C++ solution would use std::string,
(or any of the much better string classes). Doing all the passing-around,
cutting, concatenating, etc.

Without having a single new or other allocation in the *client* code of the
program. While obvoiusly doing a zillion alllocations and deallocations.
Can you describe a way to introduce a leak?
because you can't remove the problem at its root. If you want true
dynamic allocation then you need to trigger delete somehow. Unless you
add garbage collection to C++.

Sure you can, and many of us do it in practice. C++ has destructors that
are called automaticly at well defined points -- and that automation can
reliably be used to do the deletes you need. All of them.

As, unless you start doing WTF things deliberately just to prove idiots'
endless resources, destructors will be called matching constructors, and
when leaving a scope by *any* means. So the programmer's responsibility
is just to not leave non-managed resources around.

(Certainly for certain tasks you can insert GC too, I didn;t work with such
problem yet, but read success stories.)
 
J

Joshua Maurice

dragan wrote:

[snipped]>> Quite a bit of code will you need to properly destroy automatic
Another simple answer from moi: RAII. Problem solved. RAII and exceptions
are orthogonal concepts. RAII works as good with other error handling
strategies as it does with exceptions.

RAII is a great idea but you need something to kick off the destructors.
It may be an important component of error handling strategy but
exception or something else is needed to actually kick off object
destruction if error processing requires changing the context outside of
normal flow control operation.
I wouldn't call setjmp/longjmp a "context switching mechanism", but I know
what you meant. setjmp/longjmp is not an option in C++ because destructors
aren't called during "the unwinding" of the "call stack".

Exactly my point. It won't automatically,  you will have to hand-craft
some stupid mechanism like EPOC32/Symbian cleanup stack and never forget
put your important objects on it.

Uh... I think you missed the boat on this one. I think dragan meant
"return error codes" when he said "other error handling strategies".
(This includes logging the specific error then returning a generic
"failure" error code. It's still returning an error code.) Any other
kind of error handling is extremely exotic.

He meant that RAII works quite well if you use only error return codes
and do not use exceptions, and he is correct. What you do to "kick off
the destructors" is exit the current scope, generally by returning an
error code (or success code, or any kind of returning).
I am just saying: for error processing
some mechanism of context-switching is needed (BTW longjmp/setjmp is
context-switching: the context in this case are the registers including
instruction pointer or equivalent and stack frame pointers or
equivalents. In practice, it's not enough as you want application-level
"unwinding" of automatic objects as you change the stack pointers or
equivalents; that's why I am saying exceptions are convenient and cheap
without obvious drawbacks for the purpose (as long as you do not require
more flexibility in selection of error processing code targets than
exception give you), library-based cleanup-stack is worse and
longjms/setjmp is still worse.. )

I might have to disagree. Is "returning an error code" contained in
"context switching"? Returning an error code is a perfectly fine way
to handle errors, and returning an error code is not in the context of
programming what someone would call "context switching".
 
D

dragan

Ian Collins said:
dragan said:
Ian said:
paulto wrote:
dragan wrote:
[snipped]
Quite a bit of code will you need to properly destroy automatic
objects (which is quite often the required part of "error
handling". If handling of an error does not require stepping way
back, that error can be IMHO renamed to "yet another condition
arising at normal course of given business").
Another simple answer from moi: RAII. Problem solved. RAII and
exceptions are orthogonal concepts. RAII works as good with other
error handling strategies as it does with exceptions.
RAII is a great idea but you need something to kick off the
destructors. It may be an important component of error handling
strategy but exception or something else is needed to actually kick
off object destruction if error processing requires changing the
context outside of normal flow control operation.
That's exactly what RAII does for you. You manage resources so they
will be freed when the managing object goes out of scope.

That's all I had to say? I just spent a half hour replying to him. Twas
time well-spent though. I don't regret it at all. (OK, I do, but for
selfish/time reasons).

Sorry, that was bad form relying out of context.
I don't know what you meant. But I don't think so.
 

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,968
Messages
2,570,153
Members
46,699
Latest member
AnneRosen

Latest Threads

Top