writing robust software?

  • Follow


There are some general rules how to write robust software, e.g. on this
page:

http://jwinblad.com/resources/robustsw.php

like writing test cases, use modular designs, avoid global variables,
design by contract etc. But I can't find much information on more technical
advices how to write more robust software in C++, or how to implement some
of the high level ideas. Especially with C++0x there should be some nice
solutions for bugs I do often:

- uninitialized member variables
- array out of bounds errors
- memory leaks, dangling pointers etc.
- infinite loop/recursion

How can I avoid it? One idea would be more careful coding and code reviews,
but maybe there are some good language construct ideas to avoid it at all?

E.g. I could avoid uninitialized member variables, if I would use an object
for all simple types. Good compilers should optimizing it nearly away, but
I don't know, if it makes the source code more difficult to write and to
read.

Some array out of bounds errors could be avoided with functional
programming styles. E.g. the Qt metacompiler has a "foreach" keyword. With
C++ templates and for_each, or iterators, you can do something similar, but
the syntax is really cumbersome, so usually I do a normal for-loop. Maybe
C++0x helps? But how could I detect array out of bounds errors?

I don't have good ideas for memory leaks. Garbage collection would be nice
for some cases, do you know any good GC for C++? But there are problems,
where even GC doesn't help, e.g. when there are still some references to
unused objects. RAII helps sometimes, but can't be used for all problems.

For infinite loops or recursion I think there are not many things a
language construct can do for yoou. This is more a logic problem and
requires careful planning and programming.

Are there any formal verification systems for C++, like SPARK Ada?

-- 
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply fb (1526) 9/13/2010 4:56:03 PM

On Sep 13, 5:56=A0pm, Frank Buss <f...@frank-buss.de> wrote:
> .... Especially with C++0x there should be some nice
> solutions for bugs I do often:
>
> - uninitialized member variables
> - array out of bounds errors
> - memory leaks, dangling pointers etc.
> - infinite loop/recursion

Fortunately, you don't need to innovate good ideas for memory leaks:
they've been completely avoidable for 2+ decades in C++, using
Resource Initialization is Acquisition and Allocation (sp?).

The decision to incur memory leaks as a possible bug type (that is:
directly using C-style memory management rather than wrapping it in
RIAA classes like std::vector, std::list, std::unique_ptr, etc.)
should be forced on the project by the problem domain, or unavoidable
libraries.

std::array, std::deque, and std::vector provide means to convert out
of bounds operator [] into well-defined errors (member function
at()).  I lack imagination on whether std::out_of_range can be
extended into something useful for error recovery, but at least the
behavior's defined.

In general, for everything else mentioned the ideal practices are
either very thorough proofreading in conjunction with automated
regression testing, proper functional programming that isolates the
"risky" code and is rarely updated, or code generation [programming in
a higher-level language that gets rewritten to "safer" C++ by other
tools].

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Kenneth 9/14/2010 7:56:46 AM


Frank Buss wrote:
> There are some general rules how to write robust software, e.g. on this
> page:
>
> http://jwinblad.com/resources/robustsw.php
>
> like writing test cases, use modular designs, avoid global variables,
> design by contract etc. But I can't find much information on more technical
> advices how to write more robust software in C++, or how to implement some
> of the high level ideas. Especially with C++0x there should be some nice
> solutions for bugs I do often:
>
> - uninitialized member variables
> - array out of bounds errors
> - memory leaks, dangling pointers etc.
> - infinite loop/recursion
>
> How can I avoid it? One idea would be more careful coding and code reviews,
> but maybe there are some good language construct ideas to avoid it at all?

Write good unit tests, and then use tools like valgrind to catch most and very 
subtle problems

>
> Are there any formal verification systems for C++, like SPARK Ada?
>

search for "c++ static analysis"

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Vladimir 9/14/2010 8:49:13 AM

On 14 Sep., 00:56, Frank Buss <f...@frank-buss.de> wrote:
> There are some general rules how to write robust software, e.g. on this
> page:
>
> http://jwinblad.com/resources/robustsw.php

[..]

> Especially with C++0x there should be some nice solutions
> for bugs I do often:
>
> - array out of bounds errors

Use std::array instead of C arrays and ask your
favorite vendor whether the implementation has
debugging iterators.

> - memory leaks, dangling pointers etc.

What about the combination of shared_ptr and
weak_ptr?

> Some array out of bounds errors could be avoided with functional
> programming styles. E.g. the Qt metacompiler has a "foreach" keyword. Wit=
h
> C++ templates and for_each, or iterators, you can do something similar, b=
ut
> the syntax is really cumbersome, so usually I do a normal for-loop. Maybe
> C++0x helps? But how could I detect array out of bounds errors?

C++Ox provides the new range-based for statement
as in:

std::vector<T> v = ..;

for (const auto& e : v) {
   //
}

Several implementations provide debugging iterators
that validate during runtime out-of-bound situations.

HTH & Greetings from Bremen,

Daniel Kr=FCgler

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply ISO 9/14/2010 8:49:14 AM

On 2010-09-14 03:56:46 -0400, Kenneth 'Bessarion' Boyd said:

> Fortunately, you don't need to innovate good ideas for memory leaks:
> they've been completely avoidable for 2+ decades in C++, using
> Resource Initialization is Acquisition and Allocation (sp?).

<g>

RAII: Resource Acquisition Is Initialization

-- 
  Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The Standard 
C++ Library Extensions: a Tutorial and Reference (www.petebecker.com/tr1book)

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Pete 9/15/2010 6:02:54 AM

Vladimir Jovic wrote:

> Write good unit tests, and then use tools like valgrind to catch most and very
> subtle problems

Thanks, this is a practical solution to the problem.

> search for "c++ static analysis"

Do you know any good programs? A quick search results in Cppcheck, which
looks like a good beginning, but not like a mature program, like SPARK/Ada.
Ok, maybe I don't want to write and test my program against a formal
specification anyway, but maybe there is something not as complicated, but
still better than just testing plain C++ :-)

-- 
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frank 9/15/2010 6:08:23 AM

Kenneth 'Bessarion' Boyd wrote:

> Fortunately, you don't need to innovate good ideas for memory leaks:
> they've been completely avoidable for 2+ decades in C++, using
> Resource Initialization is Acquisition and Allocation (sp?).

You mean Resource Acquisition Is Initialization (RAII). I know this
concept, it is very useful, I use it for function tracing, mutex lockers
etc., and Qt uses it a lot, for QFile, QProcess etc., but I don't see how
it helps in more complicated cases, where an object has to live after
leaving some context where it was created.

> The decision to incur memory leaks as a possible bug type (that is:
> directly using C-style memory management rather than wrapping it in
> RIAA classes like std::vector, std::list, std::unique_ptr, etc.)
> should be forced on the project by the problem domain, or unavoidable
> libraries.

Sorry, I don't see how std::vector is related to RAII.

> std::array, std::deque, and std::vector provide means to convert out
> of bounds operator [] into well-defined errors (member function
> at()).  I lack imagination on whether std::out_of_range can be
> extended into something useful for error recovery, but at least the
> behavior's defined.

Thanks, you are right, I forgot about this difference between the
operator[] and at(). Ok, I have to enable execptions for my applications to
use at(), but maybe this is a good idea anyway.

std::array looks interesting, this is something from C++0x?

> In general, for everything else mentioned the ideal practices are
> either very thorough proofreading in conjunction with automated
> regression testing, proper functional programming that isolates the
> "risky" code and is rarely updated, or code generation [programming in
> a higher-level language that gets rewritten to "safer" C++ by other
> tools].

I agreee with proofreading and regression testing. Unfortunately not many
clients and other members in programming teams see the need for it. But at
least I try to do more functional style prorgamming, if possible.

-- 
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frank 9/15/2010 6:09:02 AM

Daniel Kr=FCgler wrote:

> What about the combination of shared_ptr and
> weak_ptr?

This is possible, but you still can create circles in complex object
diagrams, if you forget to use weak_ptr at the right places, but it would
be better than plain pointers. Do you think it is a good idea to rewrite =
an
application to use shared_ptr and weak_ptr, only, instead of plain
pointers? I think I have already bad memory leaks, when I some parts of m=
y
application are executed. But maybe I can find it with Valgrind, which
would be more easy instead of rewriting lots of the application.

> C++Ox provides the new range-based for statement
> as in:
>
> std::vector<T> v = ..;
>
> for (const auto& e : v) {
>    //
> }

Thanks, I'll try this with my compiler. It is not the latest GCC, so I ho=
pe
it is supported.

--
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frank 9/15/2010 10:27:08 AM

Kenneth 'Bessarion' Boyd wrote:
> Resource Initialization is Acquisition and Allocation (sp?).

You meant "Resource Acquisition Is Initialization".

Uli

--
Sator Laser GmbH
Gesch=C3=A4ftsf=C3=BChrer: Thorsten F=C3=B6cking, Amtsgericht Hamburg HR =
B62 932


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Ulrich 9/16/2010 10:55:08 AM

Frank Buss wrote:
> [...] how to write more robust software in C++, or how to implement som=
e
> of the high level ideas.

There is a book "C++ Coding Guidelines" which contains several rules whic=
h
often help avoiding bugs, unmaintainable code etc. This is really worth t=
he
money!


> Especially with C++0x there should be some nice solutions for bugs I
> do often:
>
> - uninitialized member variables

There are automated tools that detect accesses to uninitialised values.

> - array out of bounds errors

Pretty much any implementation of the C++ standardlibrary has a checked
implementation that validates iterators and indices.

> - memory leaks, dangling pointers etc.

Don't manually manage memory or other resources. Rather, code a policy fo=
r
when and how to release resources into special handle classes. In other
words, use smart pointers for objects (like auto_ptr, shared_ptr, weak_pt=
r,
which all three have their use cases) and similar classes for other
resources, too.

> - infinite loop/recursion

This one's hard to detect and avoid, because the requirements for a loop =
to
go infinite are not always obvious.

> E.g. I could avoid uninitialized member variables, if I would use an
> object for all simple types. Good compilers should optimizing it nearly
> away, but I don't know, if it makes the source code more difficult to
> write and to read.

I seem to remember a "class initialized<T>" somewhere, which automaticall=
y
initialised with "T()" unless overridden. Otherwise, it tried to behave
like a T as far as possible, like e.g. allowing assignment and conversion
to a T&.

> I don't have good ideas for memory leaks. Garbage collection would be n=
ice
> for some cases, do you know any good GC for C++?

The Boehme GC? Haven't used it though.

> RAII helps sometimes, but can't be used for all problems.

I actually disagree here to some extent, though I'm not even 100% sure wh=
at
problems you are referring to. If you'd provide an example, maybe I could
come up with a solution to it.

Cheers!

Uli

--
Sator Laser GmbH
Gesch=C3=A4ftsf=C3=BChrer: Thorsten F=C3=B6cking, Amtsgericht Hamburg HR =
B62 932


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Ulrich 9/16/2010 10:55:52 AM

Frank Buss wrote:
> Vladimir Jovic wrote:
>
>> search for "c++ static analysis"
>
> Do you know any good programs? A quick search results in Cppcheck, which
> looks like a good beginning, but not like a mature program, like SPARK/Ada.
> Ok, maybe I don't want to write and test my program against a formal
> specification anyway, but maybe there is something not as complicated, but
> still better than just testing plain C++ :-)
>

I thought more of tools like this:
http://www.parasoft.com/jsp/products/cpptest.jsp?itemId=47
I tried it, and is very good. The bad side is the price :(

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Vladimir 9/16/2010 10:57:56 AM

On Sep 15, 1:09=A0pm, Frank Buss <f...@frank-buss.de> wrote:

> You mean Resource Acquisition Is Initialization (RAII). I know this
> concept, it is very useful, I use it for function tracing, mutex lockers
> etc., and Qt uses it a lot, for QFile, QProcess etc., but I don't see how
> it helps in more complicated cases, where an object has to live after
> leaving some context where it was created.

You return it.

You should use RAII everywhere for all resources. That's the only way
to write robust code in C++.
Otherwise, your code won't be exception-safe.


> Sorry, I don't see how std::vector is related to RAII.

It follows RAII, since it acquires resources itself and releases them
in its destructor.


> Thanks, you are right, I forgot about this difference between the
> operator[] and at(). Ok, I have to enable execptions for my applications =
to
> use at(), but maybe this is a good idea anyway.

You can't use the containers part of the C++ standard library without
exceptions. There is no other error reporting mechanism.

Note also that most implementations provide a debug mode where
operator[] asserts the bounds.


> std::array looks interesting, this is something from C++0x?

TR1, which is included in C++0x.
It's also in Boost.

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Mathias 9/16/2010 3:50:21 PM

On 15 Sep., 18:27, Frank Buss <f...@frank-buss.de> wrote:
> Daniel Kr=FCgler wrote:
> > What about the combination of shared_ptr and
> > weak_ptr?
>
> This is possible, but you still can create circles in complex object
> diagrams, if you forget to use weak_ptr at the right places, but it would
> be better than plain pointers.

Arguing with this you are probably left to a very
minor subset of programming languages. Even Java
does not guarantee that it will recognize all
reference circles - so some objects may live
endlessly, if the programmer does not carefully
verify the relations.

> Do you think it is a good idea to rewrite =
> an application to use shared_ptr and weak_ptr,
> only, instead of plain pointers?

My general opinion is: "Yes, why not?" Of-course
you probably need to consider the consequences for
existing user-code, because of the API breakage.

In this case it makes probably more sense to start
to develop an independent new version and to deprecate
the old version after some reasonable transition
period. E.g. the new boost Filesystem library
does so for it's most recent development cycle.

> I think I have already bad memory leaks, when I
> some parts of my application are executed. But maybe
> I can find it with Valgrind, which would be more
> easy instead of rewriting lots of the application.

So why are you asking for solutions of this
problem, when you already have a fixed answer?

HTH & Greetings from Bremen,

Daniel Kr=FCgler

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply ISO 9/16/2010 3:51:37 PM

On Sep 15, 7:09=A0am, Frank Buss <f...@frank-buss.de> wrote:
> Kenneth 'Bessarion' Boyd wrote:
> ....
>
> You mean Resource Acquisition Is Initialization (RAII). I know this
> concept, it is very useful, I use it for function tracing, mutex lockers
> etc., and Qt uses it a lot, for QFile, QProcess etc., but I don't see how
> it helps in more complicated cases, where an object has to live after
> leaving some context where it was created.

That's where std::unique_ptr, std::shared_ptr, etc. come in.

If I was ever faced with the nightmare case where it's not at all
clear which pointers need to be weak to break cycles, I'd consider the
Trillios library.  [I haven't personally convinced myself that it
absolutely works, but it's the only one I've seen whose smart pointers
even try to cope with this and it will handle the cases that commonly
come up in scientific computing.]

> > The decision to incur memory leaks as a possible bug type (that is:
> > directly using C-style memory management rather than wrapping it in
> > RIAA classes like std::vector, std::list, std::unique_ptr, etc.)
> > should be forced on the project by the problem domain, or unavoidable
> > libraries.
>
> Sorry, I don't see how std::vector is related to RAII.

If you know the size a std::vector needs to be, it can be constructed
at that size (with minor assumptions on the underlying data type).
E.g.

std::vector<int> x(5);

starts off with five default-initialized elements.

This is on top of the usual std::bad_alloc throwing copy constructors
the standard library containers use.  The most glaring issue is that
(quite reasonably) the standard containers don't auto-delete raw
pointers for you when erasing.

> std::array looks interesting, this is something from C++0x?

Yes, std::array is new in C++0X.  If the project is allowed to use the
Boost libraries, boost::array is a pretty good mockup.

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Kenneth 9/16/2010 3:54:18 PM

Frank Buss wrote:

> You mean Resource Acquisition Is Initialization (RAII). I know this
> concept, it is very useful, I use it for function tracing, mutex =
lockers
> etc., and Qt uses it a lot, for QFile, QProcess etc., but I don't see =
how
> it helps in more complicated cases, where an object has to live after
> leaving some context where it was created.

std::auto_ptr, the upcoming std::unique_ptr, boost::shared_ptr, etc.

> Sorry, I don't see how std::vector is related to RAII.

It replaces C-style code like:

  T* p = new T[500];

  // ...

  delete p;   // let's cross our fingers and hope we get here

You cannot use std::auto_ptr in this situation.

--
Gerhard Menzl

Non-spammers may respond to my email address, which is composed of my =
full name, separated by a dot, followed by at, followed by "fwz", =
followed by a dot, followed by "aero".



      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Gerhard 9/16/2010 5:11:16 PM

On Sep 16, 2:51=A0pm, Daniel Kr=FCgler <daniel.krueg...@googlemail.com>
wrote:
> Even Java
> does not guarantee that it will recognize all
> reference circles - so some objects may live
> endlessly, if the programmer does not carefully
> verify the relations.

Meh? I don't want to go too far into off topic land, but that
insinuation is a little flawed. /If I recall correctly/, /I think/
that Java does not require any garbage collection at all. The standard
does not require an implementation to reclaim memory for future use,
ever. However, as a matter of fact, desktop implementations of Java
will collect a 'group of objects which form a cycle' if they're not
otherwise reachable. So yes, technically Java does not require
collecting unreachable object cycles /because/ it doesn't require any
garbage collection at all. Your insinuation that Java has a special
case in standard or practice for reclamation of object cycles is
incorrect.

This is subject to the usual constraint that reclamation of any
particular unreachable object may be delayed a very long time. While
any particular 'cycle of objects which are otherwise unreachable'
might live for a very long time, if all your program did was allocate
these, then your (desktop) JVM would find (most of) them and collect
(most of) them when free memory was low.

PS: This is not to say that Java programs cannot have memory leaks.
It's just that memory leaks in Java manifest in different ways than C+
+, generally as the result of an ever expanding collection - things go
in, but never come out. The contained objects are reachable so they
will not be collected, but they're unneeded by the program logic so
they constitute an effective memory leak.

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Joshua 9/17/2010 2:51:35 AM

On Sep 16, 2:50=A0pm, Mathias Gaunard <loufo...@gmail.com> wrote:
> On Sep 15, 1:09=A0pm, Frank Buss <f...@frank-buss.de> wrote:
>
> > You mean Resource Acquisition Is Initialization (RAII). I know this
> > concept, it is very useful, I use it for function tracing, mutex lockers
> > etc., and Qt uses it a lot, for QFile, QProcess etc., but I don't see how
> > it helps in more complicated cases, where an object has to live after
> > leaving some context where it was created.
>
> You return it.
>
> You should use RAII everywhere for all resources. That's the only way
> to write robust code in C++.
> Otherwise, your code won't be exception-safe.

To continue, my preferred "interpretation: if RAII is as follows: RAII
is the practice of ensuring that all resources, at all times, have a
clearly identifiable owner (or owners) who are responsible for freeing
that resource on all code paths in a destructor. If you need to
allocate some object inside of a function and return it to the caller,
then you can still use RAII. When you allocate that object, give it an
owner, such as an std::auto_ptr. When the function ends, hand off
ownership to someone else, such as by returning that std::auto_ptr.
The caller then can do whatever he wants, including give ownership to
boost::shared_ptr or some other kind of data structure. RAII does not
disallow ownership handoffs, nor does it disallow shared collective
ownership ala boost::shared_ptr. It's just the practice to guarantee
that all resources have an owner at all times who will free that
resource through the use of destructors.

By ensuring that at any one point in time all resources have an owner
(or owners) who will free that resource tthrough automatic implicit
invocation of a destructor (except for handoffs which need careful
attention), it becomes much easier to reason about resource leaks and
prevent them. It's easier to review code in isolation by asking "Ok,
who owns that object?" If no one owns it, and an exception is thrown,
you might leak it.

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Joshua 9/17/2010 2:52:31 AM

Daniel Kr�gler wrote:

> Arguing with this you are probably left to a very
> minor subset of programming languages. Even Java
> does not guarantee that it will recognize all
> reference circles - so some objects may live
> endlessly, if the programmer does not carefully
> verify the relations.

Do you have an example? AFAIK the GC algorithm of Java just tests, which
objects are reachable from threads and stacks and deletes the rest, so any
graph of circular references will be deleted, too, if it is not reachable
any more.

> So why are you asking for solutions of this
> problem, when you already have a fixed answer?

This was just an idea, I'm still searching for a good solution. Using
Valgrind may find some memory leaks, but I can't be sure that it will find
any leaks in my program, because there are too many different execution
paths. So it may fix some problems, but in the long run a clean program,
where it is not possible from theory to produce memory leaks, would be
better.

-- 
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frank 9/17/2010 2:53:05 AM

Ulrich Eckhardt wrote:

> There is a book "C++ Coding Guidelines" which contains several rules which
> often help avoiding bugs, unmaintainable code etc. This is really worth the
> money!

I can't find it. Do you mean this book?

http://www.amazon.com/exec/obidos/ASIN/0321113586

-- 
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frank 9/17/2010 2:53:25 AM

Kenneth 'Bessarion' Boyd wrote:

> On Sep 15, 7:09=A0am, Frank Buss <f...@frank-buss.de> wrote:
>> Kenneth 'Bessarion' Boyd wrote:
>> ....
>>
>> You mean Resource Acquisition Is Initialization (RAII). I know this
>> concept, it is very useful, I use it for function tracing, mutex lockers
>> etc., and Qt uses it a lot, for QFile, QProcess etc., but I don't see how
>> it helps in more complicated cases, where an object has to live after
>> leaving some context where it was created.
> 
> That's where std::unique_ptr, std::shared_ptr, etc. come in.

Thanks, this makes sense. E.g. if I store a shared_ptr in a vector, I can
leave the context where I created the object, but maybe the vector is a
member variable of some other object, which is created in some other
context and if this object is destroyed, the vector and finally the
containing objects are destroyed. I didn't saw the bigger picture of RAII,
just the small auto_ptr like coding styles. So if I use shared_ptr (and
weak_ptr etc.) and I don't create some circular reference with shared_ptrs,
everything should be fine.

> If I was ever faced with the nightmare case where it's not at all
> clear which pointers need to be weak to break cycles, I'd consider the
> Trillios library.  

I can't find it, do you have a link?

> Yes, std::array is new in C++0X.  If the project is allowed to use the
> Boost libraries, boost::array is a pretty good mockup.

I'm lucky in this project: I can use anything which is supported by the
compiler, if I can convince my colleagues that it is useful and not too
esoteric C++ (some of them are good at assembler and a bit C, but some
things of C++ which I'm trying to use are a closed book to them).

But the target is an embedded system, so e.g. I can't use tools like
Valgrind on it, because it is not available for ARM/Linux and it would
require too much memory, but I have abstracted the hardware related parts
and most of the application can be compiled for standard X11, too, so at
least I can test some parts on a normal PC.

-- 
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frank 9/17/2010 2:53:48 AM

On 17 Sep., 10:51, Joshua Maurice <joshuamaur...@gmail.com> wrote:
> On Sep 16, 2:51=A0pm, Daniel Kr=FCgler <daniel.krueg...@googlemail.co=
m>
> wrote:
>
> > Even Java
> > does not guarantee that it will recognize all
> > reference circles - so some objects may live
> > endlessly, if the programmer does not carefully
> > verify the relations.
>
> Meh? I don't want to go too far into off topic land, but that
> insinuation is a little flawed. /If I recall correctly/, /I think/
> that Java does not require any garbage collection at all. The standard
> does not require an implementation to reclaim memory for future use,
> ever. However, as a matter of fact, desktop implementations of Java
> will collect a 'group of objects which form a cycle' if they're not
> otherwise reachable. So yes, technically Java does not require
> collecting unreachable object cycles /because/ it doesn't require any
> garbage collection at all. Your insinuation that Java has a special
> case in standard or practice for reclamation of object cycles is
> incorrect.
>
> This is subject to the usual constraint that reclamation of any
> particular unreachable object may be delayed a very long time. While
> any particular 'cycle of objects which are otherwise unreachable'
> might live for a very long time, if all your program did was allocate
> these, then your (desktop) JVM would find (most of) them and collect
> (most of) them when free memory was low.

My description was flawed, I agree. What I actually should have
said is that there is not much difference between a program
that does have an infinite leak and one where the the life-time
of unused objects becomes very long. IMO any code that
"manually" handles these cases by doing *active* clean-up,
are some form of necessary bug-fix and I don't consider
this kind of bug-fix different in quality from bug-fixes that
would place a missing weak_ptr at the right place - and this
was the situation Frank was referring to.

Greetings from Bremen,

Daniel Kr=FCgler

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply ISO 9/17/2010 1:26:52 PM

Frank Buss wrote:
> Do you mean this [link deleted] book?

Yes, it's "C++ Coding Standards" not "Guidelines".

Uli

-- 
Sator Laser GmbH
Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932


      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Ulrich 9/17/2010 3:27:53 PM

On Sep 17, 3:53 am, Frank Buss <f...@frank-buss.de> wrote:
> Kenneth 'Bessarion' Boyd wrote:

> > If I was ever faced with the nightmare case where it's not at all
> > clear which pointers need to be weak to break cycles, I'd consider the
> > Trillios library.  
>
> I can't find it, do you have a link?

Sorry, didn't remember to check open tabs when composing.  It's the
Trilinos library I'd reach for.

http://trilinos.sandia.gov/

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Kenneth 9/18/2010 3:46:10 AM

More or less some solution already mentioned, forget me for
reiterating it:

> - uninitialized member variables

Use proper constructors with member initialization lists.
Default ctors can mean two things:
- default is always OK for me
- I do not care

> - array out of bounds errors

Use some container, for example std::... containers with iterators.
There would be never out of bound errors.
For special cases hand made containers can be fabricated, i.e. for
example if auto_ptr is needed to be hold.

> - memory leaks, dangling pointers etc.

Use correct design then the objects' lifetime is properly known at
coding time. This will lead you to use the proper smart pointer and
not forget destruction if needed.
ValgrinD and mdb (for Solaris) is good for memory corruption
detection, but sometimes you can get many false positives, and you
cannot try all the execution paths.

> - infinite loop/recursion

No remedy for such errors. Maybe you can put something into other
processes and you can kill them when there is no answer in the
expected time, i.e. you think the process is in a infinite loop.


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Krisztian 9/19/2010 12:09:20 PM

On Sep 15, 5:27 pm, Frank Buss <f...@frank-buss.de> wrote:
> Daniel Kr=FCgler wrote:
> > What about the combination of shared_ptr and
> > weak_ptr?

> This is possible, but you still can create circles in complex
> object diagrams, if you forget to use weak_ptr at the right
> places, but it would be better than plain pointers. Do you
> think it is a good idea to rewrite an application to use
> shared_ptr and weak_ptr, only, instead of plain pointers?
> I think I have already bad memory leaks, when I some parts of
> my application are executed. But maybe I can find it with
> Valgrind, which would be more easy instead of rewriting lots
> of the application.

In general, smart pointers are not the silver bullet other
posters seem to suggest.  They are convenient for some specific
cases (e.g. giving value semantics, or something similar, to
polymorphic objects), but most of the time, you shouldn't be
using dynamically allocated memory at all unless the object in
question has a specific, deterministic lifetime.  (And if the
object has a specific, deterministic lifetime, you know when to
delete it, no?)

In my experience, dangling pointers cause more problems than
leaking memory.  The object has been destructed, because the
program logic require that it be destructed at that time, but
somewhere, some code wasn't informed.  The only practical
solution I've found for this is to use the Boehm collector: set
a flag when the object is destructed, and assert that the flag
isn't set at the start of each function.  (The Boehm collector
ensures that the memory underlying the object will not be
recycled for some other object as long as there are any pointers
to it.)

--
James Kanze

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply James 9/28/2010 8:42:23 AM

James Kanze wrote:

> In my experience, dangling pointers cause more problems than
> leaking memory.  The object has been destructed, because the
> program logic require that it be destructed at that time, but
> somewhere, some code wasn't informed.

Do you have an example? I'm not an expert, but I think everything can be
solved with smart pointers and careful programming, because then you don't
need raw delete operators any more and with weak_ptr you can test with
"expired" and "lock" if the referenced object still exists, if you can't be
sure for some specific case.

-- 
Frank Buss, http://www.frank-buss.de
piano and more: http://www.youtube.com/user/frankbuss

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Frank 9/29/2010 5:24:18 AM

In article <16d2hifwg028e.pji7kgjgmxgg$.dlg@40tude.net>,
Frank Buss  <fb@frank-buss.de> wrote:
>James Kanze wrote:
>
>> In my experience, dangling pointers cause more problems than
>> leaking memory.  The object has been destructed, because the
>> program logic require that it be destructed at that time, but
>> somewhere, some code wasn't informed.
>
>Do you have an example? I'm not an expert, but I think everything can be
>solved with smart pointers and careful programming, because then you don't
>need raw delete operators any more and with weak_ptr you can test with
>"expired" and "lock" if the referenced object still exists, if you can't be
>sure for some specific case.

Well, everything soluble can be solved by careful programming, so
that's a red herring!

But you have repeated the Great Garbage Collector Myth.  It is NOT
true that such designs eliminate whole classes of problem - they
eliminate some cases and turn others into logical errors, which
are much harder to locate.

Let's say that you have a state object, which is manipulated by a
module State, but accessed by many other modules (e.g. Compute).
Compute caches a pointer to the state, State then replaces the
state by a new one and assumes that the old one now has a zero
use count.  Unfortunately, Compute will still continue to use the
old one.

That can get a lot worse, where a module Munge may also update the
state.  If it caches a pointer, you can get the effect where some
changes are executed but have no effect.  And so on.

But you also get the failure to call destructors, which can cause
chaos when the state is supposed to be saved on file, or where some
system resource (e.g. shared memory) needs to be freed.  Memory
leaks, nothing - get a bad descriptor or segment leak and your
whole system gradually clogs up and dies.


Regards,
Nick Maclaren.

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply nmm1 9/29/2010 6:05:58 PM

26 Replies
488 Views

(page loaded in 2.222 seconds)

Similiar Articles:


















7/25/2012 3:26:55 PM


Reply: