Problem with calloc

D

ds

Hello all,

I have a problem with calloc I have never seen before. I am migrating
some C code to C++ and at some part in the C code there is a calloc
that creates an array of structures. Now in the C++ version, the
structures are classes with virtual access functions. I am working on
linux with g++ and it seems that the _vptr part of the class is null.
Further use of these classes causes a segmentation fault. Of course if
I use new everything is ok. I wonder if this is a limitation of the
calloc implementation or if it is platform specific...

Thanks a lot!!
 
R

Rolf Magnus

ds said:
Hello all,

I have a problem with calloc I have never seen before. I am migrating
some C code to C++ and at some part in the C code there is a calloc
that creates an array of structures. Now in the C++ version, the
structures are classes with virtual access functions. I am working on
linux with g++ and it seems that the _vptr part of the class is null.
Further use of these classes causes a segmentation fault. Of course if
I use new everything is ok. I wonder if this is a limitation of the
calloc implementation or if it is platform specific...

calloc just fills all the allocated bytes with zero. This might be
sufficient for POD types, but for non-POD classes, it isn't. The objects
must be properly constructed, and calloc doesn't do this. That's why there
is operator new.
 
J

Jim Langston

ds said:
Hello all,

I have a problem with calloc I have never seen before. I am migrating
some C code to C++ and at some part in the C code there is a calloc
that creates an array of structures. Now in the C++ version, the
structures are classes with virtual access functions. I am working on
linux with g++ and it seems that the _vptr part of the class is null.
Further use of these classes causes a segmentation fault. Of course if
I use new everything is ok. I wonder if this is a limitation of the
calloc implementation or if it is platform specific...

Thanks a lot!!

Yeah, pain in the neck isn't it? That is one big difference between C's
structures and C++'s classes. A class that is not POD doesn't necessesarily
want everything to be initialized to 0. This is something I ran across when
working with some C code converting it to c++. The C code had something
like:

struct Foo
{
char String[100];
int SomeInt;
};

Foo* Bar;

Bar = malloc( sizeof Foo );
// Now fill the memory with 0's

Well, this was actually taking place in very differnet places (global
variables, etc...). And I innocently tried to add a class to the structure.
The same as:

struct Foo
{
std::string Foo;
int SomeInt;
}

And it took me a while to track down the zero filling of the memory and that
the constructor was never being called.

It's usually not a simple search and replace to fix this code, because some
C code can get a little spagetti like, I spent days tracking down all the
places this program was zero allocating memory.
 
V

Victor Bazarov

Jim said:
ds said:
Hello all,

I have a problem with calloc I have never seen before. I am migrating
some C code to C++ and at some part in the C code there is a calloc
that creates an array of structures. Now in the C++ version, the
structures are classes with virtual access functions. I am working on
linux with g++ and it seems that the _vptr part of the class is null.
Further use of these classes causes a segmentation fault. Of course
if I use new everything is ok. I wonder if this is a limitation of
the calloc implementation or if it is platform specific...

Thanks a lot!!

Yeah, pain in the neck isn't it? That is one big difference between
C's structures and C++'s classes. A class that is not POD doesn't
necessesarily want everything to be initialized to 0. This is
something I ran across when working with some C code converting it to
c++. The C code had something like:

struct Foo
{
char String[100];
int SomeInt;
};

Foo* Bar;

Bar = malloc( sizeof Foo );
// Now fill the memory with 0's

Well, this was actually taking place in very differnet places (global
variables, etc...). And I innocently tried to add a class to the
structure. The same as:

struct Foo
{
std::string Foo;
int SomeInt;
}

And it took me a while to track down the zero filling of the memory
and that the constructor was never being called.

Just to explain Jim's point: do NOT use 'malloc' or 'calloc' for non-
POD types (especially when they can or do contain virtual functions)
because that's going to interfere with (or simply forgo) proper
construction of your objects.

What's the alternative? 'new' and 'new[]'. When in Rome...
It's usually not a simple search and replace to fix this code,
because some C code can get a little spagetti like, I spent days
tracking down all the places this program was zero allocating memory.

"Zero allocating" sounds wrong. You meant 'zero-initialising', right?

V
 
P

peter koch

Yeah, pain in the neck isn't it? That is one big difference between
C's structures and C++'s classes. A class that is not POD doesn't
necessesarily want everything to be initialized to 0. This is
something I ran across when working with some C code converting it to
c++. The C code had something like:
struct Foo
{
char String[100];
int SomeInt;
};
Foo* Bar;
Bar = malloc( sizeof Foo );
// Now fill the memory with 0's
Well, this was actually taking place in very differnet places (global
variables, etc...). And I innocently tried to add a class to the
structure. The same as:
struct Foo
{
std::string Foo;
int SomeInt;
}
And it took me a while to track down the zero filling of the memory
and that the constructor was never being called.

Just to explain Jim's point: do NOT use 'malloc' or 'calloc' for non-
POD types (especially when they can or do contain virtual functions)
because that's going to interfere with (or simply forgo) proper
construction of your objects.

What's the alternative? 'new' and 'new[]'. When in Rome...

My advice would be to replace malloc and friends with new, std::vector
and std::string. This should be the first step in a conversion, the
second being to write constructors and destructors and ensure RAII is
in use everywhere. There is no reason to use new[] unless you are in a
very special situation.
 
J

Jim Langston

Victor Bazarov said:
Jim said:
ds said:
Hello all,

I have a problem with calloc I have never seen before. I am migrating
some C code to C++ and at some part in the C code there is a calloc
that creates an array of structures. Now in the C++ version, the
structures are classes with virtual access functions. I am working on
linux with g++ and it seems that the _vptr part of the class is null.
Further use of these classes causes a segmentation fault. Of course
if I use new everything is ok. I wonder if this is a limitation of
the calloc implementation or if it is platform specific...

Thanks a lot!!

Yeah, pain in the neck isn't it? That is one big difference between
C's structures and C++'s classes. A class that is not POD doesn't
necessesarily want everything to be initialized to 0. This is
something I ran across when working with some C code converting it to
c++. The C code had something like:

struct Foo
{
char String[100];
int SomeInt;
};

Foo* Bar;

Bar = malloc( sizeof Foo );
// Now fill the memory with 0's

Well, this was actually taking place in very differnet places (global
variables, etc...). And I innocently tried to add a class to the
structure. The same as:

struct Foo
{
std::string Foo;
int SomeInt;
}

And it took me a while to track down the zero filling of the memory
and that the constructor was never being called.

Just to explain Jim's point: do NOT use 'malloc' or 'calloc' for non-
POD types (especially when they can or do contain virtual functions)
because that's going to interfere with (or simply forgo) proper
construction of your objects.

What's the alternative? 'new' and 'new[]'. When in Rome...
It's usually not a simple search and replace to fix this code,
because some C code can get a little spagetti like, I spent days
tracking down all the places this program was zero allocating memory.

"Zero allocating" sounds wrong. You meant 'zero-initialising', right?

Yeah, I guess I just made "zero allocating" up without even realizing it,
meaning allocating memory then zero filling it.
 
D

ds

Hello all

and thanks for the answers!!! I really got unstuck, I was wondering
why calloc wouldn't allocate memory the same way for an object just as
new (since I already could observe the difference). Note, that without
virtual methods, calloc works. However it is true that the object is
not constructed appropriately as is the case with new. However, if I
explicitly construct the elements using

::new ((void*)ptr) TYPE;

where ptr is the pointer to the object and TYPE the type of the
object, the object is properly constructed. I of course understand
that this is not the correct way. However, since I plan to perform the
migration iteratively, I would like for the moment to maintain the "C"
styke memory management, check that the algorithm works, and change it
alltogether to any prper C++ memory management scheme that we will
decide on.

Thanks for all the answers and help!!!
 
V

Victor Bazarov

ds said:
Hello all

and thanks for the answers!!! I really got unstuck, I was wondering
why calloc wouldn't allocate memory the same way for an object just as
new (since I already could observe the difference). Note, that without
virtual methods, calloc works. However it is true that the object is
not constructed appropriately as is the case with new. However, if I
explicitly construct the elements using

No need to cast to void*.
where ptr is the pointer to the object and TYPE the type of the
object, the object is properly constructed. I of course understand
that this is not the correct way.

Actually, it's fine. It's called "placement new", and it exists
specifically for doing what you did, constructing in the memory you
have acquired somehow, beforehand.

Just don't 'delete' that pointer. Use the explicit destructor call
and then deallocate your memory as you normally would:

ptr->~TYPE();
free(ptr);
However, since I plan to perform the
migration iteratively, I would like for the moment to maintain the "C"
styke memory management, check that the algorithm works, and change it
alltogether to any prper C++ memory management scheme that we will
decide on.

Up to you.

V
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top