 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Peter Dimov Guest
|
Posted: Sat Jun 04, 2005 2:29 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
David Abrahams wrote:
| Quote: | "Peter Dimov" <pdimov (AT) gmail (DOT) com> writes:
Le Chaud Lapin wrote:
so you can relax and not ASSERT it to death."
No.
Using types with a greater range than necessary helps the receiver
of the value check the assumptions of the sender. Testing whether
the value is out of range is an easy and surprisingly effective way
of catching bugs.
In the signed/unsigned case specifically, C and C++ allow you to
return -1 from a function returning unsigned, sometimes even without
a warning. So making the return type unsigned doesn't automatically
mean that the return value will be correct. It will be nonnegative,
but still incorrect.
Yeah, this one is debatable, IMO. I understand what Peter's saying,
but I still prefer to use unsigned. The logic is that when a signed
negative number wraps, it is almost always closer to zero than to
INT_MIN, so it will wrap to a very large positive number and whatever
assert() I'm using to check that the value isn't too large is also
going to catch these cases. It's a tradeoff between expressiveness
and economy of code on the one hand, and absolute ability to catch
errors on the other. I happen to think the balance goes in favor of
using unsigned, but I understand why others don't.
|
On rereading this a few times, I'm still not sure what you are saying, but
if your point is that assert( x < n ) with an unsigned x will catch negative
values, this is basically a repeat of what I said in the first paragraph
about using types with a greater range than necessary.
The interesting case is when you have no inherent upper limit. Signed with >
0 and unsigned with <= INT_MAX are equivalent if you put the arbitrary upper
limit of INT_MAX on the number, but I've never seen someone asserting x <=
INT_MAX when x is unsigned int, or even asserting an upper limit at all.
Negative values in a signed int have the advantage of being obviously
incorrect in such a context, even for someone that doesn't know what the
code is about, and assert( x > 0 ) is much easier to understand, compared to
assert( x < -2048 ) with an unsigned x.
Of course a language that enforces the valid range at runtime would
encourage exactly the opposite coding style, using the smallest type that
can hold all valid values. Such a language would write the assertions for
us. But C++ does not. ;-)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Branimir Maksimovic Guest
|
Posted: Sat Jun 04, 2005 2:30 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Allan W wrote:
| Quote: | kanze (AT) gabi-soft (DOT) fr wrote (formatting added):
There are really only two questions with regards to
standardization:
(1) can it be used usefully,
With regards to garbage collection, the first seems to be
obviously true.
Not sure it's obvious -- not even sure what "used usefully" means --
but I agree that GC would be useful for certain types of programs,
if we can pin down the answers to certain questions such as if,
when and how the destructor is fired.
|
Since we have auto objects there is no need to fire destructors
at all during gc cycle, but only if one explicitelly does delete.
| Quote: |
and
(2) does it cost less than the advantages.
The second is more complex;
introducing garbage collection does have an effect on the
existing language, and the cost of this effect will not be
zero. But it is an analysis which can be carried out calmly,
without accusing those in favor of garbage collection of being
incompetent in algorithms, or such. An argument along the lines
of "garbage collection is too expensive because..." is quite
acceptable.
Yes.
Seems to me that there's a simple answer, too. Like most
features of the C++ language, we simply need to ensure that
programs which do NOT use it have zero (runtime) cost.
|
That can be easilly done, just:
//std::gc::disable();
T* p = new T;
delete p;
| Quote: |
Just because that answer is simple doesn't make it easy.
I'd guess that the most difficult part would be some way of
recognizing *at a language level* that GC is, or is not, used.
|
There is no need to recognize that gc is used or not if explicit
deallocation is allowed.
| Quote: | (I am NOT talking about a compiler setting!) A related question
is how to mix code that DOES use GC, with code that DOES NOT.
If explicit delete would be allowed then that would be simple. |
Problems arise in question of what kind of gc would work there?
I certainly doesn't want one that moves data around.
Other then that hans boehm gc seems to work fine without any language
support(just use GC_MALLOC in globar operator new),
but it seems little bit of help from implementation can improve
it to work faster and differ between pointer and int.
There is no need to add anything special in language syntax.
Just std::gc::* functions for behavior control and some help
from compiler to reduce scan range.
Greetings, Bane.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Antoun Kanawati Guest
|
Posted: Sat Jun 04, 2005 2:33 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Le Chaud Lapin wrote:
| Quote: | Llewelly wrote:
What makes you think these two statements are mutually exclusive? I
don't believe there has ever been a useful feature that has not
been used to cover up a 'more fundamental problem'.
But there is a difference between a problem with the language and a
problem with the programmer. IMO, the problem of GC in C++ is most
often with the programmer. [snip...]
In the case of GC, I am saying that the programmer starts off with
something of bad form, "fixes" it with GC, and ends up with something
that has perfect memory usage and bad form.
|
GC, like many other useful features, allows for more 'lazy' programming,
an excellent practice where you focus your effort on the core problem
that cannot be solved by some mindless automation like the garbage
collector or the compiler. There are cases where the mindless automaton
proves to be overly mindless, and you will need to intervene, but,
generally, such cases are identifiable, and therefore addressable by
introducing memory management as part of the core problem.
Generally, memory management is a derivative problem, typically related
to the programming language you have chosen, not to the problem you're
trying to solve.
--
A. Kanawati
[email]NO.antounk.SPAM (AT) comcast (DOT) net[/email]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Antoun Kanawati Guest
|
Posted: Sat Jun 04, 2005 2:35 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Stephen Howe wrote:
| Quote: | Others are arguing that GC is sufficiently useful to C++ that
it should be integrated into the language.
And those arguments will fall on deaf ears,until 2 questions are answered:
1. Is the proposed GC an optional part of C++ such that all those who have
no use of it are not forced to use it; or is it compulsory?
2. If it is optional, will all vendors be forced to supply GC or would it be
acceptable to supply a C++ compiler lacking a GC?
|
After all these years, C++ practice has evolved to the point where
destructors have become a key component of resource management.
This will make the introduction of a low-impact GC definition a rather
hairy task.
For example, in Java, Object.finalize (the Java destructor) lies in
obscurity because it is non-deterministic: if it runs, you're not sure
when; and then again, it may not run at all; then, comes the problem
of reviving dead references during the execution of finialize(). The
net result is that nobody ever writes destructors in Java.
So, even before the compulsory/optional question, I would really like
to know what GC would look like in C++, and how it plays with existing
practices.
--
A. Kanawati
[email]NO.antounk.SPAM (AT) comcast (DOT) net[/email]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Antoun Kanawati Guest
|
Posted: Sat Jun 04, 2005 2:37 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: | Le Chaud Lapin wrote:
In the case of GC, I am saying that the programmer starts off
with something of bad form, "fixes" it with GC, and ends up
with something that has perfect memory usage and bad form.
So you're claiming that the only possible use of garbage
collection is fixing broken programs. That doesn't correspond
to the reasons which the proponents of garbage collection are
putting forth. If you don't want garbage collection, why not
address those reasons, instead of inventing some imaginary uses
of garbage collection.
|
And, in agreement, I chime in as follows:
If your programming language is Java, Scheme, or Perl, how do you
tell the broken programs from the unbroken ones? all of them use
GC, whether they like it or not. All other things being equal,
GC does not seem to be a factor in the elimination or creation of
badness in programming: people screw up in every programming
language.
Also, writing programs that are free of memory management errors
is not a cost-free proposition. With GC, the cost of making
programs free of memory management errors will go down, and that's
a net benefit. There is a reason shared_ptr is so loved, and why
Purify and similar products are still in business; bad programming
alone is not a sufficient reason.
--
A. Kanawati
[email]NO.antounk.SPAM (AT) comcast (DOT) net[/email]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Le Chaud Lapin Guest
|
Posted: Sat Jun 04, 2005 12:26 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Daniel James wrote:
| Quote: | In article
news:<1117649979.600952.101330 (AT) g47g2000cwa (DOT) googlegroups.com>, Le Chaud
Lapin wrote:
... never create functions that have int parameters representing
quantities that are inherently non-negative. The fruits of this
discipline is that all concomitant problems with what to do about
all those ASSERT/try/catch blocks will never need to be addressed.
I believe that is a false argument. The same program logic errors that
might lead to an int becoming unexpectedly negative will lead to an
unsigned int acquiring an unexpectedly large positive value. Assertions
(or whatever) in the code are not made less necessary by the change of
type.
|
Good point. I must admit that in 99.9% of time, I never check an
unsigned int argument to see if it is too big.
Now that I think about it, I have never used an ASSERT in all my years
of programming. I do check return values from functions though.
-Chaud Lapin-
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Le Chaud Lapin Guest
|
Posted: Sat Jun 04, 2005 12:27 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Peter Dimov wrote:
| Quote: | Using types with a greater range than necessary helps the receiver of the
value check the assumptions of the sender. Testing whether the value is out
of range is an easy and surprisingly effective way of catching bugs.
|
I am curious. Let's say you design a custom object that takes an
unsigned int argument that tells it how big it should make itself (how
many inserts it should do on a container member, for example):
struct Pig
{
std::list<Food> stomach;
void eat_corn (unsigned int count_of_cobs);
} ;
Pig().eat_corn(2U << 30);
Now we know that no pig, no matter how greedy, can eat a billion cobs
of corn. How would you handle this? What would be your threshold for
too many cobs of corn or would you even bother to specify a threshold?
-Chaud Lapin-
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Le Chaud Lapin Guest
|
Posted: Sat Jun 04, 2005 12:28 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Nicola Musatti wrote:
| Quote: | You fail to consider that GC may be a very reasonable solution to
memory management in many concrete situations. For instance, in the
application I'm working on when the user selects one of his/her
customers a rather complicate data structure is created. When the user
selects another customer I have no use for the previous customer's
data. Why do I have to waste programming time to
free such memory? If I had GC I wouldn't have to sprinkle my code with
shared_ptr's or some alternative scheme.
|
Because you are using the heap. This is a good example of what I was
referring to. Naturally, I have no doubt of your ability to wield C++
as you please, but I wonder if your object could have been implemented
concretely. This is the essence of my original argument: I suspect
that most objects actually can if containers are heavily employed.
| Quote: | When all's said and done it all boils down to how much client classes
see of the internal details of supplier classes. The use of abstract
classes helps minimize the interdependencies among implementation
details of different subsystems, thus reducing compile time and making
it possible to provide patches by replacing only parts of an
application.
|
This again illustrates what I was saying. I understand that there are
a lot of people who like PIMPL. I'm battling some colleagues at work
now over it. Yes, concrete makes you have to recompile big chunks of
code, and yes there is the heap mismatch problem with DLL's, let alone
the problem of changing the class definition in dynamically updated
code. But concrete scales very well, and if I'm not mistaken, for each
time you find a really good concrete class, you're proving a primtive
that someone else really can use as a fundamental primitive in their
new design, abstract or concrete.
Perhaps I am biased. Until recently, I was working alone on massive
programs (not so much in terms of lines of code but scope of function
), and I could not have possibly kept up if it were not for the
built-in copy/assign semantics in C++ that come with the concrete
model. This model allows the mind to tackle massive problems because
compiler does most of the work in maintaining the structural integrity
system. There is also the benefit of true hierarchical form. To see
the converse, imagine how hard it would be to think about a chemical
factory if, instead of for every container of chemical, there was a
little note where the container should have been saying, "The container
you are looking for is down the street. Follow this piece of string to
get to it." With the abstract model and PIMPL, insuring structural
integrity becomes much more involved, sometimes too close for comfort,
IMO.
Ironically, we want the same thing from C++: for it to take care of
memory management in a way that relieves the mind.
-Chaud Lapin-
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Sat Jun 04, 2005 12:40 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Peter Dimov wrote:
| Quote: | Of course a language that enforces the valid range at runtime
would encourage exactly the opposite coding style, using the
smallest type that can hold all valid values. Such a language
would write the assertions for us. But C++ does not.
|
But it can be made to do so. All you have to do is define a
class with the appropriate properties:-).
Doing so has a certain cost, of course. If the error is so rare
that the benefits don't outweigh the cost, why bother?
--
James Kanze mailto: [email]james.kanze (AT) free (DOT) fr[/email]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Sat Jun 04, 2005 12:43 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Robert Kindred wrote:
| Quote: | "Peter Dimov" <pdimov (AT) gmail (DOT) com> wrote in message
news:d7pdel$qo2$1 (AT) domitilla (DOT) aioe.org...
In the signed/unsigned case specifically, C and C++ allow you
to return -1 from a function returning unsigned, sometimes
even without a warning. So making the return type unsigned
doesn't automatically mean that the return value will be
correct. It will be nonnegative, but still incorrect.
This reminds me of Ray Lischner's question as to why currency
is a signed value in some program. Your answer is better than
mine.
|
The answer to that one is obvious: so it can keep track of my
bank account after my wife's taken the credit card.
--
James Kanze mailto: [email]james.kanze (AT) free (DOT) fr[/email]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Sat Jun 04, 2005 6:09 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Antoun Kanawati wrote:
| Quote: | Stephen Howe wrote:
Others are arguing that GC is sufficiently useful to C++ that
it should be integrated into the language.
And those arguments will fall on deaf ears,until 2 questions
are answered:
1. Is the proposed GC an optional part of C++ such that all those who
have
no use of it are not forced to use it; or is it compulsory?
2. If it is optional, will all vendors be forced to supply GC or
would it be
acceptable to supply a C++ compiler lacking a GC?
After all these years, C++ practice has evolved to the point
where destructors have become a key component of resource
management.
This will make the introduction of a low-impact GC definition
a rather hairy task.
|
I don't see any relationship. The two things are orthogonal,
and unrelated.
| Quote: | For example, in Java, Object.finalize (the Java destructor)
|
Object.finalize is in no way related to C++ destructors.
| Quote: | lies in obscurity because it is non-deterministic: if it runs,
you're not sure when; and then again, it may not run at all;
then, comes the problem of reviving dead references during the
execution of finialize(). The net result is that nobody ever
writes destructors in Java.
|
The reason no one writes destructors in Java is because they
don't exist. Period -- finalize is NOT a destructor.
The Java equivalent to destructors is a finally clause. And
correct Java programs do use them.
| Quote: | So, even before the compulsory/optional question, I would
really like to know what GC would look like in C++, and how it
plays with existing practices.
|
That is, of course, a valid question. One to which there are
several answers. I don't think that there is a real consensus
on all points, but I think that there is a consensus on several
points :
-- Whatever else is decided, auto and static variables continue
to behave exactly as they do today.
-- I think it is also generally agreed that delete should
continue to work as it does today, even if the object in
question would otherwise be garbage collected.
-- It must be possible to write C++ programs which don't use
garbage collection.
Beyond that, I think it is still an open point as to whether
constructors should be called when an object is collected, or
whether we should provide some additional function, such as
finalize. The exact way garbage collection would be integrated
into C++ is still up in the air: is it part of the type system,
do we have two separate new, etc.
--
James Kanze mailto: [email]james.kanze (AT) free (DOT) fr[/email]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Sat Jun 04, 2005 6:11 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Matthias wrote:
| Quote: | You are perfectly right that the "root of the problem" that
causes people to ask for GC is object-oriented programming: It
is exactly when you have a "mess" of objects, each with its
own identity and lifetime, but heavily interacting/ linked
with each other that memory management gets cumbersome.
|
I agree with the rest of what you are saying, but garbage
collection was used long before OO came along. Functional
languages, for example, generally use it extensively. In fact,
it can be useful in any language which supports dynamic
allocation.
But to get back to the root of the argument. I can see someone
deciding against garbage collection in specific cases. I don't
use it myself in my current application. More for political
reasons than for technical ones, but I think that the choice is
justified. What bothers me somewhat is that the option to use
it isn't as readily available as it should be (i.e. if it were
part of the standard). What bothers me a lot more is the idea
that the decision is to be made on some arbitrary name-calling
basis, with claims that those favoring garbage collection are
somehow incompetent, or don't understand algorithms, and not on
the basis of cost-benefits analysis.
--
James Kanze mailto: [email]james.kanze (AT) free (DOT) fr[/email]
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 pl. Pierre Sémard, 78210 St.-Cyr-l'École, France +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Peter Dimov Guest
|
Posted: Sat Jun 04, 2005 6:14 pm Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Le Chaud Lapin wrote:
| Quote: | Peter Dimov wrote:
Using types with a greater range than necessary helps the receiver
of the value check the assumptions of the sender. Testing whether
the value is out of range is an easy and surprisingly effective way
of catching bugs.
I am curious. Let's say you design a custom object that takes an
unsigned int argument that tells it how big it should make itself (how
many inserts it should do on a container member, for example):
struct Pig
{
std::list<Food> stomach;
void eat_corn (unsigned int count_of_cobs);
} ;
Pig().eat_corn(2U << 30);
Now we know that no pig, no matter how greedy, can eat a billion cobs
of corn. How would you handle this? What would be your threshold for
too many cobs of corn or would you even bother to specify a threshold?
|
It depends. I probably shouldn't be asserting a threshold in eat_corn,
because 64-bit pigs can eat 2^31 corns (it may take a while, of course). I
might assert a threshold on the caller side, where I have a better idea what
I expect to be passing.
If Pig::eat_corn specifies an upper limit (Pig::max_size?) I'd assert
against that.
If practice indicates that values of count_of_cobs over a specific threshold
are a frequent occurence and are always caused by bugs, I might assert
against that (arbitrary) threshold in Pig::eat_corn to catch the remaining
bugs and prevent new ones. This would technically make my implementation of
the Pig spec non-conforming, of course. (Like asserting non-NULL in
auto_ptr::operator-> is non-conforming but useful.)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Llewelly Guest
|
Posted: Mon Jun 06, 2005 7:18 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
"Le Chaud Lapin" <unoriginal_username (AT) yahoo (DOT) com> writes:
| Quote: | Llewelly wrote:
What makes you think these two statements are mutually exclusive? I
don't believe there has ever been a useful feature that has not
been used to cover up a 'more fundamental problem'.
But there is a difference between a problem with the language and a
problem with the programmer.
[snip] |
All real problems involve multiple parties, any of whom can do
something to effect a solution. The only difference between 'a
problem with the language' and 'a problem with the programmer' is
who does the work.
The important question is, which party (or parties) can solve the
problem with the least redundant effort.
Since GC works well for many kinds of programs (not all!), a few
implementors implementing garbage collection is a lot less effort
than thousands of development teams re-inventing it.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Llewelly Guest
|
Posted: Mon Jun 06, 2005 7:19 am Post subject: Re: Pathology Of Bad Software Architecture |
|
|
Antoun Kanawati <antounk (AT) comcast (DOT) net> writes:
| Quote: | Stephen Howe wrote:
Others are arguing that GC is sufficiently useful to C++ that
it should be integrated into the language.
And those arguments will fall on deaf ears,until 2 questions are answered:
1. Is the proposed GC an optional part of C++ such that all those who have
no use of it are not forced to use it; or is it compulsory?
2. If it is optional, will all vendors be forced to supply GC or would it be
acceptable to supply a C++ compiler lacking a GC?
After all these years, C++ practice has evolved to the point where
destructors have become a key component of resource management.
This will make the introduction of a low-impact GC definition a rather
hairy task.
For example, in Java, Object.finalize (the Java destructor) lies in
obscurity because it is non-deterministic: if it runs, you're not sure
when; and then again, it may not run at all;
^^^^^^^^^^^^^^^^^^^^^ |
Read that line a few times. It says, in letters 10 feet tall,
Object.finalize() is NOT a destructor!
Amoung other things, the description of finalize() contains: 'The
finalize method may take any action, including making this object
available again to other threads; ' See
[url]http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#finalize([/url])
A C++ destructor cannot make the object available again.
But the best explanation of the differences is probably:
http://www.hpl.hp.com/techreports/2002/HPL-2002-335.html
[snip]
| Quote: | So, even before the compulsory/optional question, I would really like
to know what GC would look like in C++, and how it plays with existing
practices.
[snip] |
The simplest option is probably to define the runtime to never call
destructors for objects stored in the garbage-collected heap.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Powered by phpBB © 2001, 2006 phpBB Group
|