Wednesday, February 18, 2015

Digest for comp.lang.c++@googlegroups.com - 25 updates in 5 topics

Torsten Mueller <muellerto@runbox.com>: Feb 18 09:29AM +0100

My C++ application compiled for many years with gcc, up to current
version 4.9.2. But now after a compiler update it suddenly says "malloc
is undefined", and this message comes from far above, from inside the
cstdlib header.
 
Note: I don't use malloc at all, not a single time. My code is proper
C++. But C++ himself uses malloc in the new operator.
 
What I had to do for getting a workaround was to include stdlib.h before
cstdlib - but can this be the solution??? cstdlib still includes
stdlib.h, of course, it always did.
 
In my application I use also boost (1.57). And boost has an own cstdlib
header. Could this be the reason?
 
Has anyone had this problem in the last time, malloc is undefined?
 
T.M.
"Lőrinczy Zsigmond" <zsiga@nospam.for.me>: Feb 18 09:47AM +0100

Please quote the complete message,
it's not clear if this is a compiler-message or a linker-message.
"Øyvind Røtvold" <orotvold@gmail.com>: Feb 18 09:56AM +0100


> What I had to do for getting a workaround was to include stdlib.h before
> cstdlib - but can this be the solution??? cstdlib still includes
> stdlib.h, of course, it always did.
 
Is cstdlib supposed to be self-contained? If so try to include it
first in your source file. If it fails there's an error in your
compiler which should be reported - or, more likely, an error in your
compiler installation that you should fix.
 
 
 
> In my application I use also boost (1.57). And boost has an own cstdlib
> header. Could this be the reason?
 
If you include this cstdlib header then anything boost think proper
could happen, including what you describes. Remove boots from the
equation and try again.
 
 
--
.. Ųyvind - soon to appear in a kill file near you.
.. Ignorance can be cured; stupidity is forever.
Torsten Mueller <muellerto@runbox.com>: Feb 18 10:07AM +0100


> Please quote the complete message,
> it's not clear if this is a compiler-message or a linker-message.
 
Sure it is clear. I never spoke about the linker, I spoke about the
compiler and headers. It's a true compiler problem, happening again and
again in every single source file.
 
T.M.
"Lőrinczy Zsigmond" <zsiga@nospam.for.me>: Feb 18 10:15AM +0100


> > Please quote the complete message,
 
> It's a true compiler problem,
> happening again and again in every single source file.
 
That's why you don't quote the complete message. Ok.
Torsten Mueller <muellerto@runbox.com>: Feb 18 10:19AM +0100


> Is cstdlib supposed to be self-contained?
 
I'm sure.
 
> If it fails there's an error in your compiler which should be reported
> - or, more likely, an error in your compiler installation that you
> should fix.
 
I try to get a preprocessor output this afternoon to see the real code
and which header is really included and which conditional code is indeed
compiled.
 
Interesting is that cstdlib also uses a handful of other primitive
C-functions, about 20, but only malloc is unknown.
 
T.M.
Torsten Mueller <muellerto@runbox.com>: Feb 18 10:21AM +0100


>> It's a true compiler problem,
>> happening again and again in every single source file.
 
> That's why you don't quote the complete message. Ok.
 
Dear Hungarian friend, I can't quote because I'm currently not on this
machine, OK?
 
T.M.
"Lőrinczy Zsigmond" <zsiga@nospam.for.me>: Feb 18 11:04AM +0100

On 2015-02-18 09:29, Torsten Mueller wrote:
> In my application I use also boost (1.57). And boost has an own cstdlib
> header. Could this be the reason?
 
But of course. Try to complie boost-less example programs.
David Brown <david.brown@hesbynett.no>: Feb 18 11:38AM +0100

On 18/02/15 09:29, Torsten Mueller wrote:
> header. Could this be the reason?
 
> Has anyone had this problem in the last time, malloc is undefined?
 
> T.M.
 
The usual way to proceed with this sort of thing is to figure out a
minimum sample that demonstrates the problem - this should help you
figure out if boost is the problem or there is something else wrong.
And then you can post the example along with the error messages (when
you are on the right computer, of course). Also include details of the
compiler and command-line switches.
 
You said that your code worked with gcc up to 4.9.2 - but after an
update it failed. Since 4.9.2 is the latest released version of gcc,
are you trying a development version? Did you get the new version from
a different place (in which case it might be packaged with different
libraries or other differences)?
Torsten Mueller <muellerto@runbox.com>: Feb 18 12:10PM +0100


> You said that your code worked with gcc up to 4.9.2 - but after an
> update it failed. Since 4.9.2 is the latest released version of gcc,
> are you trying a development version?
 
No, it's official 4.9.2. But on a Linux machine you always have still
other parts of software defining the concrete build environment,
especially glibc and libc++ (and a lot of others ...)
 
My situation is as follows: I have two Linux machines, an old one and a
new one, both with gcc 4.9.2, but with a different bunch of libs. The
old one compiles fine, the new one doesn't know malloc in cstdlib. Sure
I have glibc on this machine, sure I have also all the glibc-headers,
sure malloc is an existing, documented and well known function. I never
changed anything in these files or in the permissions, all is standard,
but cstdlib doesn't know malloc.
 
OK, for me it's a hint that noone says, yes, that's right, they changed
something last sunday in glibc, malloc is banned for ever, or so.
 
T.M.
David Brown <david.brown@hesbynett.no>: Feb 18 01:10PM +0100

On 18/02/15 12:10, Torsten Mueller wrote:
 
> No, it's official 4.9.2. But on a Linux machine you always have still
> other parts of software defining the concrete build environment,
> especially glibc and libc++ (and a lot of others ...)
 
OK, that's clearer - you said "after a compiler update", rather than
"after a system update" or "after a library update".
 
 
> OK, for me it's a hint that noone says, yes, that's right, they changed
> something last sunday in glibc, malloc is banned for ever, or so.
 
> T.M.
 
Can you do a quick comparison of the headers between the machines, to
see if something has dramatically changed there? It won't be the
libraries that have changed, as you haven't got that far (they only
affect the linking stage).
scott@slp53.sl.home (Scott Lurndal): Feb 18 02:17PM


>OK, for me it's a hint that noone says, yes, that's right, they changed
>something last sunday in glibc, malloc is banned for ever, or so.
 
>T.M.
 
Compile on both systems using -E and compare the resulting output. That
should tell you where, exactly, the malloc is defined (and the path to get
there) in the working example; which should lead you to the difference.
 
IIRC, some versions of gcc used to implicitly declare malloc.
ram@zedat.fu-berlin.de (Stefan Ram): Feb 18 12:22AM

I have written the following program:
 
#include <iostream>
#include <ostream>
 
struct c
{ int v;
 
c( int const x ): v( x )
{ ::std::cout << "constructor of instance #" << v << ".\n"; }
 
~c(){ ::std::cout << "destructor of instance #" << v << ".\n"; }
 
void print(){ ::std::cout << "I am instance #" << v << ".\n"; }};
 
int main()
{ c o = * new c( 1 );
o.print();
o = * new c( 2 ); /* overwrite */
o.print(); }
 
The program prints:
 
constructor of instance #1.
I am instance #1.
constructor of instance #2.
I am instance #2.
destructor of instance #2.
 
In the line marked with »/* overwrite */«, instance #1 in the
variable »o« is overwritten with another instance of the same
class c if I understand it correctly.
 
I thought that this overwriting kind-of »destroys« the instance #1
and that this might invoke the destructor of instance #1. But no,
it does never print »destructor of instance #1.«.
 
I am still a beginner with respect to some parts of C++, so
I have to ask here why my expectations are wrong.
ram@zedat.fu-berlin.de (Stefan Ram): Feb 18 12:59AM

>> o = * new c( 2 ); /* overwrite */
>> o.print(); }
>By assigning another instance to the pointer you lost the first. Raw
 
But both »o« and »* new c( 2 )« are not pointers, but rather
an object and a temporary, respectively, as far as I understand it.
 
»new c( 2 )« is a pointer, but »*« makes a temporary from
the pointer, as far as I understand it.
 
So, the assignment »o = * new c( 2 )« has an object on the
left and a temporary on the right.
 
>Nay my friend. You have demonstrated a memory leak.
 
(I am aware that the »new« creates a memory leak missing the
corresponding »delete«, but this was not my primary concern,
so - for simplification - I omitted the »delete«.)
ram@zedat.fu-berlin.de (Stefan Ram): Feb 18 02:03PM

>other hand, you have two values (1 and 2), copy them over across
>instances and print out with misleading messages, so there is no wonder
 
So, in C++, an assignment of the kind
 
object0 = object1
 
can be thought of as a field-by-field copy (at least in the
simple case of POD-like objects) from object1 to object0
that does not change the existence status of object0 or object1.
David Brown <david.brown@hesbynett.no>: Feb 18 10:42AM +0100

On 17/02/15 23:51, Barry Schwarz wrote:
>>> uint8_t?
 
>> The rules of C - a "char" is the smallest addressable unit of memory.
 
> That doesn't stop sub-byte bit fields.
 
Bit-fields cannot be accessed except as part of their containing struct.
In particular, you cannot take the address of a bitfield (§6.5.3.2 of
N1570, if you want chapter and verse).
 
> There is also no restriction
> in the standard that prohibits multiple objects sharing an address.
 
I can't find the right paragraph for this one (but I'm sure others here
or in comp.lang.c can do so - the rules being the same for C and C++).
But different objects must have different addresses, unless they are
part of a union. This is why classes without data members (or virtual
functions) have size 1 rather than size 0 - the different addresses
allow them to be distinguished.
eao197@gmail.com: Feb 18 01:32AM -0800

SObjectizer[1] is a small framework which was created under influence of several approaches like Actor Model and Publish/Subscribe. It was used as in-house tool for developing several business-critical applications. It is distributed as OpenSource project under NewBSD-license since 2006. But unlike CAF (former libcppa) or Theron frameworks it is not widely known because almost all articles and docs were in Russian.
 
Now I glad to represent two introductory presentations about this tool in English. I hope someone will find them interesting and useful.
 
The presentations could be found here:
 
http://eao197.blogspot.com/2015/02/prog-two-introductory-presentations.html
 
 
Best regards,
Yauheni
 
---
[1] https://sourceforge.net/projects/sobjectizer/
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Feb 18 12:30AM

On 18/02/2015 00:22, Stefan Ram wrote:
> it does never print »destructor of instance #1.«.
 
> I am still a beginner with respect to some parts of C++, so
> I have to ask here why my expectations are wrong.
 
That code is mental mate; you have two memory leaks as you are create
two objects on the heap and in the first case you are *copy
constructing* 'o' on the stack with one of them and in the second case
you are *assigning* to o with one of them.
 
This is what you code should look like:
 
c o(1); // construction
o = c(2); // assignment
 
No heap allocation with new required.
 
/Flibble
Christopher Pisz <nospam@notanaddress.com>: Feb 17 06:50PM -0600

On 2/17/2015 6:22 PM, Stefan Ram wrote:
> it does never print »destructor of instance #1.«.
 
> I am still a beginner with respect to some parts of C++, so
> I have to ask here why my expectations are wrong.
 
Nay my friend. You have demonstrated a memory leak.
By assigning another instance to the pointer you lost the first. Raw
pointers do not automatically invoke the destructor when assigned. After
all, you may not want it destroyed, but simply to point to something
else, if you had another way of getting at it, like a second pointer
elsewhere. As is, it is dangling, lost forever.
 
If you would like to have that behavior, you may want to use a
std::shared_ptr or one of its kin.
 
 
 
 
-----
I have chosen to troll filter/ignore all subthreads containing the
words: "Rick C. Hodgins", "Flibble"
So, I won't be able to see or respond to any such messages
-----
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Feb 18 12:55AM

On 18/02/2015 00:50, Christopher Pisz wrote:
 
> words: "Rick C. Hodgins", "Flibble"
> So, I won't be able to see or respond to any such messages
> -----
 
Mr Flibble is very cross.
"Christopher J. Pisz" <cpisz@austin.rr.com>: Feb 17 07:20PM -0600

On 2/17/2015 6:59 PM, Stefan Ram wrote:
> the pointer, as far as I understand it.
 
> So, the assignment »o = * new c( 2 )« has an object on the
> left and a temporary on the right.
 
True, kind of. the <new> returns a pointer. You de-referenced it, and
assigned it to an object on the stack, whom was already default
constructed, but you saw no message for that or the assignment because
you didn't implement the default constructor or the assignment operator
yourself.
 
So really, you have 3 instances and the message is erroneous, because it
is actually the instance on the stack getting destroyed, while both on
the heap are leaked.
 
 
 
> (I am aware that the »new« creates a memory leak missing the
> corresponding »delete«, but this was not my primary concern,
> so - for simplification - I omitted the »delete«.)
 
Oh, ok, I didn't realize you did it on purpose.
 
Implement the default constructor and the assignment operator with
messages and see if it makes sense.
"Lőrinczy Zsigmond" <nospam@for.me>: Feb 18 06:50AM +0100

On 2015.02.18. 1:22, Stefan Ram wrote:
> { ::std::cout << "constructor of instance #" << v << ".\n"; }
 
> ~c(){ ::std::cout << "destructor of instance #" << v << ".\n"; }
 
> void print(){ ::std::cout << "I am instance #" << v << ".\n"; }};
 
If your idea is making constructors and debuggers visible,
then you are on the right way, but it still could be improved
 
struct c
{ int v;
 
c( int const x ): v( x )
{ ::std::cout << "constructor of instance #" << v << ".\n"; }
 
c(const c &from): v(from.v)
{ ::std::cout << "copy constructor of instance #" << v << ".\n"; }
 
c& MyClass::operator= (const c &from)
{ printf ("assignment (operator=) new=%d old=%d\n",
this->v, other->v);
this->v = other= v; /* do we need this? */
return *this; }
 
~c(){ ::std::cout << "destructor of instance #" << v << ".\n"; }
 
void print(){ ::std::cout << "I am instance #" << v << ".\n"; }};
 
Note: either include <cstdio> or change 'printf' to a bunch of <<'s
"Lőrinczy Zsigmond" <nospam@for.me>: Feb 18 06:57AM +0100


> ~c(){ ::std::cout << "destructor of instance #" << v << ".\n"; }
 
> void print(){ ::std::cout << "I am instance #" << v << ".\n"; }};
 
> Note: either include <cstdio> or change 'printf' to a bunch of <<'s
 
Lot of bugs here:)
 
c& MyClass::operator= (const c &from)
{ printf ("assignment (operator=) new=%d old=%d\n",
from.v, this->v);
this->v = from.v; /* do we need this? */
return *this; }
Paavo Helde <myfirstname@osa.pri.ee>: Feb 18 12:44AM -0600

ram@zedat.fu-berlin.de (Stefan Ram) wrote in news:destructors-
 
> In the line marked with »/* overwrite */«, instance #1 in the
> variable »o« is overwritten with another instance of the same
> class c if I understand it correctly.
 
This is because you have mixed up instances with values. In your program
you have 3 instances of class c, 2 of them are leaked and so there is
only a single destructor call when the object o goes out of scope. On the
other hand, you have two values (1 and 2), copy them over across
instances and print out with misleading messages, so there is no wonder
one gets confused.
 
You can have an example with 2 instances (of class c) and no memory leaks
as well:
 
#include <iostream>
#include <ostream>
#include <memory>
 
struct c
{ int v;
 
c( int const x ): v( x )
{ ::std::cout << "constructor of instance #" << v << ".\n"; }
 
~c(){ ::std::cout << "destructor of instance #" << v << ".\n"; }
 
void print(){ ::std::cout << "I am instance #" << v << ".\n"; }};
 
int main()
{ std::unique_ptr<c> o(new c( 1 ));
o->print();
o = std::unique_ptr<c>(new c( 2 )); /* overwrite */
o->print(); }
 
This prints:
constructor of instance #1.
I am instance #1.
constructor of instance #2.
destructor of instance #1.
I am instance #2.
destructor of instance #2.
 
 
 
For some more fun, here is another example having 2 instances and no
memory leaks. This one is probably even more confusing ;-)
 
#include <iostream>
#include <ostream>
 
struct c
{ mutable int v;
 
c( int const x ): v( x )
{ ::std::cout << "constructor of instance #" << v << ".\n"; }
 
void operator=(const c& y) const {v = y.v;}
 
~c(){ ::std::cout << "destructor of instance #" << v << ".\n"; }
 
void print() const { ::std::cout << "I am instance #" << v << ".\n";
}};
 
int main()
{ const c& o = c( 1 );
o.print();
o = c( 2 ); /* overwrite */
o.print(); }
 
constructor of instance #1.
I am instance #1.
constructor of instance #2.
destructor of instance #2.
I am instance #2.
destructor of instance #2.
"Tobias Müller" <troplin@bluewin.ch>: Feb 18 06:50AM

> it does never print »destructor of instance #1.«.
 
> I am still a beginner with respect to some parts of C++, so
> I have to ask here why my expectations are wrong.
 
There seems to be a misunderstanding of the difference between objects and
pointer to objects.
I suspect that you are coming from java where this distinction is not
visible.
A reference in Java (often just called an
object) corresponds to a _pointer_ in C++.
 
This is what your program actually means, step by step:
int main()
{
c o; // creates an object (not a reference!) on the stack
{ // temporary scope for second statement in your code
c* anon = new c( 1 ); // create an anonymous object on the heap
o = *anon; // assign the _content_ of the anonymous object to o.
} // pointer to anonymous object is lost -> memory leak
o.print();
{ // temporary scope for 4th statement in your code
c* anon = new c( 2 ); // create an anonymous object on the heap
o = *anon; // assign the _content_ of the anonymous object to o.
} // pointer to anonymous object is lost -> memory leak
o.print();
}
 
Tobi
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: