• Create Account

# Object tries to destroy itself after Creation.

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

28 replies to this topic

### #1RoundPotato  Members   -  Reputation: 82

Like
0Likes
Like

Posted 28 September 2013 - 06:03 PM

Hi,

I create an object in allocated space and it immediately after calls its own destructor, I can use the Object after, but it messes up the object because destructor deletes internal pointers and does cleaning.

// prepare pointer
SomeObject *objs;

// allocate memory
void* memory = malloc(sizeof(SomeObject)*5);

// point to memory as SomeObject pointer
objs = (SomObject*)memory;

// try to create object in third(out of five) memory slot
objs[2] = SomeObject();

// later use is messed up because destructor has been called.


I found out that this was indeed the case by putting "std::cout"s in both constructor and destructor to tell when they are called.

This is as low as was possible to debug. Does anyone happen to know why this happens ?

### #2Brother Bob  Moderators   -  Reputation: 6474

Like
4Likes
Like

Posted 28 September 2013 - 07:26 PM

The fourth line creates an unnamed temporary object, assigns it to objs[2], and then the temporary object is destroyed. That's the destructor you're seeing. If this messes up the object being assigned to, then your class does not properly implement its assingment operator to copy the resources.

But also, you're not assigning to a valid object. None of the objects in objs have been constructed, and assignment assumes you're assigning to an already constructed object. You have to properly construct the objects after allocating the memory; if you insist on allocating the memory with malloc, then you can construct the objects in the memory buffer with placement new.

### #3RoundPotato  Members   -  Reputation: 82

Like
0Likes
Like

Posted 28 September 2013 - 07:41 PM

Well, it does not implement an assignment operator at all. "Assignment assumes that you already have constructed objects" ... how would you construct those ? I thought you pass the object to a memory location via assignment and it would be constructed there.

You did say "placement new" which I have recently read about, and the thing that scares me is the warning about alignment, I have no idea how would you align objects or even if the memory location should be instead, or both, neither how

If you could kindly explain me those concepts, it would be much appreciated.

Edited by RoundPotato, 28 September 2013 - 07:43 PM.

### #4Hodgman  Moderators   -  Reputation: 19620

Like
6Likes
Like

Posted 28 September 2013 - 08:36 PM

To fix your code, here's how you use placement new

// allocate memory
void* memory = malloc(sizeof(SomeObject)*5);

// cast to SomeObject pointer so array indexing works below
SomeObject *objs = (SomObject*)memory;

// try to create object in 3rd, 2nd and 1st (out of five) memory slots
SomeObject *thirdObj  = new(&objs[2]) SomeObject();
SomeObject *secondObj = new(objs + 1) SomeObject();
SomeObject *firstObj  = new( memory ) SomeObject();

// the return value is just a cast of the allocation:
// thirdObj  == &objs[2] / same pointer
// secondObj == &objs[1] / same pointer
// firstObj  == &objs[0] / same pointer
// firstObj  == (SomeObject*)memory / same pointer

// objs[0], objs[1] and objs[2] are now valid C++ objects, which you have to destruct before freeing the allocation
objs[0].~SomeObject();
objs[1].~SomeObject();
objs[2].~SomeObject();
Free(memory);

You should always follow the rule of three when writing C++ code though. At the very least, if your class has a destructor, but you don't want to implement copying/assignment, then you must declare them as being private in order to prevent the compiler from automatically implementing them:

class SomeObject
{
public:
SomeObject();
~SomeObject();
private:
SomeObject( const SomeObject& );
SomeObject& operator=( const SomeObject& );
};

Regarding alignment, there's no standard answer -- it depends on the compiler/CPU that you're targeting.
Say that and int variable is 4 bytes, some CPU's will crash if you try to use an int that isn't aligned to an address that's a multiple of 4. An x86 CPU won't crash, but it may run slower if memory isn't aligned correctly.
Usually, for any primitive type, you can think of sizeof(Type) as being it's required alignment value. For structures, you can use sizeof for it's largest member. e.g. a struct with a 64-bit (8byte) variable and a 16-bit (2byte) variable should be aligned to an address that's a multiple of 8 bytes.
If you're lazy, you can just align everything to 16 bytes, which will work for 99.9% of cases on PC
On MSVC, you can use _aligned_malloc/_aligned_free instead of malloc/free to get aligned allocations.

But yes, you should feel pretty uneasy when using placement new and aligning your own memory -- these tasks should generally only be performed deep inside low-level container classes like std::vector.

From your other thread, it sounds like what you're looking for is a pool container. I have an open source one (header, implementation), but it's not exactly documented or readable

If you're still learning C++, I'd really recommend just using a simple/straightforward solution that you're more comfortable with for now. KISS is always a useful principle to follow in order to keep out bugs and get things done.

Edited by Hodgman, 28 September 2013 - 08:42 PM.

### #5RoundPotato  Members   -  Reputation: 82

Like
0Likes
Like

Posted 28 September 2013 - 09:33 PM

Might be worth a note that, getting the pointers from placement new isn't actually necessary(creation of "firstObj" , he compiler would normlly scream about typecasting "memory " into a type pointer), but you most likely made that so it would be more obvious to me.

With your example of having a stuct with two variables 8B and 2B , you suggest aligning it to 8B, I would assume the structure would need 16B then ? How would that also work out if sizeof(exampleStruct) return 10B then ? would each member require a minimum of 8B if it's actual size is below? What happens random 0's are placed ? Sorry I'm confused :/

Also how would you actually do the aligning ?

Another question is, I saw on some random forum when doing random "googling" that "malloc" aligns by default with 8 bytes or something similar, any possible confirmations ?

Edited by RoundPotato, 28 September 2013 - 09:39 PM.

### #6Hodgman  Moderators   -  Reputation: 19620

Like
2Likes
Like

Posted 28 September 2013 - 09:56 PM

With your example of having a stuct with two variables 8B and 2B , you suggest aligning it to 8B, I would assume the structure would need 16B then ? How would that also work out if sizeof(exampleStruct) return 10B then ? would each member require a minimum of 8B if it's actual size is below?

When you create an array of structures, they're spaced sizeof(structure) apart. If the struct requires 8B alignment (because it has an 8B member), but the size is 10B, then the first element will be aligned correctly, but the 2nd/3rd/etc elements in the array won't be aligned correctly.
To simplify this, the compiler will insert padding into structures, making them bigger than they need to be.

e.g. Try running this code:

struct Example { long long eightBytes; short twoBytes; };
printf( "%d", sizeof(Example) );

It should print 16, not 10! The compiler inserts 6 "padding" bytes after the last member, to ensure that the size of the struct is alignable. The first member requires an alignment of 8, the second member requires an alignment of 2.
As long as the start of the array is aligned to a multiple of 8 (or 16, or 32...), then every element in the array will also be correctly aligned, and every member will be correctly aligned.
e.g. say the array starts at address #48 -- array[0].eightBytes is at #48, a multiple of 8, and array[0].twoBytes is at #56, a multiple of 2. array[1].eightBytes is at #64, a multiple of 8, and so on.

Also how would you actually do the aligning ?

It used to be fairly complicated, so I would've suggested just using an alignment of 16 for everything. Since C++11 though, as well as sizeof(T), we also now have alignof(T).

e.g. for MS Visual Studio, you can use the aligned malloc/free functions like this:

template<class T>
T* AllocArray( int count )
{
return (T*)_aligned_malloc( sizeof(T)*count, alignof(T) );
}
void FreeArray( void* ptr )
{
_aligned_free( ptr );
}

Example* myArray = AllocArray<Example>( 5 );

new(&myArray[2]) Example();

myArray[2].~Example();

FreeArray( myArray );

Instead of using MSVC-specific functions, the portable C++11 version of the above is:

template<class T>
T* AllocArray( int count )
{
return (T*)aligned_alloc( alignof(T), sizeof(T)*count );
}
void FreeArray( void* ptr )
{
free( ptr );
}

"malloc" aligns by default with 8 bytes or something similar, any possible confirmations ?

Yes, (IIRC...) this is true -- malloc will always return an allocation that is correctly aligned for any standard primitive type, which in practice, means it's aligned to 8 bytes.

However, there are also non-standard primitive types, such as __m128 which is an SSE variable representing 4 floats stored together, and has a size/alignment of 16-bytes. That's why I recommend using 16 bytes as the "default" alignment value, not 8 bytes as the standard recommends...

The above example of alignof(T) always selects the correct alignment though, so you don't have to worry about picking a good default one-size-fits-all

Edited by Hodgman, 28 September 2013 - 10:06 PM.

### #7Servant of the Lord  Crossbones+   -  Reputation: 12827

Like
1Likes
Like

Posted 28 September 2013 - 11:31 PM

You should always follow the rule of three when writing C++ code though. At the very least, if your class has a destructor, but you don't want to implement copying/assignment, then you must declare them as being private in order to prevent the compiler from automatically implementing them

Or, in C++11, you'd explicitly 'delete' them; and if you want to show others that you really desire default-generated functions, then you can explicitly mark them as 'default'.

class SomeObjectInCpp11
{
public:
SomeObject() = default; //Have the compiler generate it.
SomeObject( const SomeObject& ) = delete; //Make sure others can't use it.
SomeObject& operator=( const SomeObject& ) = delete;
~SomeObject(); //Define it yourself

//For objects managing data, these are also useful to implement
//(usually as a swap of the data pointers, rather than copying the data).
SomeObject( SomeObject&& ); //Move-constructor
SomeObject& operator=(SomeObject&&); //Move-assignment operator
};

People joke that in C++11 the 'rule of three' is now the 'rule of five'. While not a strict requirement, the two additional functions can speed up the code using the class by a great deal, and is usually easy to implement.

Rule of Three in C++ - Wikipedia

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

### #8wintertime  Members   -  Reputation: 1365

Like
6Likes
Like

Posted 29 September 2013 - 04:20 AM

Wow.

The first thing you should do is, forget that malloc exists as long as you want to program in C++ and dont try to work around doing it wrong by hacking around it with wrong C-typecasts or placement new. Operator new and delete got introduced into C++ precisely to avoid errors with not calling constructors and destructors.

Just do it like this and have an automagically stack-allocated array of 2 readily constructed SomeObject objects:

SomeObject objects[2];


Or like this to get a resizable vector:

// at beginning of file
#include <vector>

// later when you need it
std::vector<SomeObject> objects;
objects.resize(2); // or add objects in some other way, for example with push_back



Or if you can't resist doing it in an inefficient, unsafe, contrived way and want to get memory leaks if you forget something:

SomeObject *objects=nullptr;
try {
objects=new SomeObject[2];
// do whatever you need here
delete[] objects;
} catch(...) {
delete[] objects;
throw;
}


### #9TheChubu  Crossbones+   -  Reputation: 2125

Like
0Likes
Like

Posted 29 September 2013 - 06:29 AM

^ This. I'm not seeing yet why you're specifically avoiding 'new' (unless you're doing it for learning purposes, in which case do what you will ).

Edited by TheChubu, 29 September 2013 - 06:31 AM.

### #10RoundPotato  Members   -  Reputation: 82

Like
-3Likes
Like

Posted 29 September 2013 - 10:07 AM

@Hodgman,Thank you for yet another great and educative reply !

Isn't both 8B and 16B alignments "heart stabbing" when you might have only one or a few occurrences of those 8B/16B and lots of say, 2B or 1B in a struct (Are classes the same ?) ? I believe the same applies to simple variables even ?

I could use the '#pragma pack(1)' (I think it's MSVC specific though) to ensure no padding is fit but that would make the whole programming experience within that program to be a layer much closer to assembly (because I would need to control/check/test every single variable) wouldn't it ?

@Servant, thanks for pointing that out, I usually try to avoid these complexities of implemeting those myself as defaults are satisfactory, but it's good to know that I can explicitly state those 'default' and 'delete'.

@wintertime, I'm afraid I'll disagree here.

The first example occupies the stack which is always not suitable for big amounts of dynamic data.

The second example uses the vector which is overhead for something which should be simple(the actual simplicity, not the user simplicity that hides all complexity in that class).

And the third example is not suitable (read reply below). If I needed dynamic memory allocation with object creation and constructor/destructor calling, calling "new" is in no way "inefficient" or "unsafe", just clean up with an easy to use 'delete' or 'delete []' as appropriate.

@TheChubu, low-details that affect performance, I actually need to pre-allocate memory for dynamic object creation with manually creating each object there, so I need only memory nothing more.

Edited by RoundPotato, 29 September 2013 - 11:37 AM.

### #11ultramailman  Prime Members   -  Reputation: 1125

Like
0Likes
Like

Posted 29 September 2013 - 12:22 PM

I don't think it's good to use malloc with objects in c++. If you want to pre-allocate a fixed chunk of memory, consider using new[] POD objects.

### #12RoundPotato  Members   -  Reputation: 82

Like
-1Likes
Like

Posted 29 September 2013 - 06:46 PM

I don't think it's good to use malloc with objects in c++. If you want to pre-allocate a fixed chunk of memory, consider using new[] POD objects.

You cannot allocate memory with "new[]" without creating the objects and calling their constructors unless "placement new" is used. Unless you mean some "new char[]" which doesn't sound like it's much better in regards to alignment I have no idea what would that use.

Edited by RoundPotato, 29 September 2013 - 06:49 PM.

### #13RoundPotato  Members   -  Reputation: 82

Like
-1Likes
Like

Posted 29 September 2013 - 06:57 PM

For convenience I'll copy over the questions that are still open:

Isn't both 8B and 16B alignments "heart stabbing" when you might have only one or a few occurrences of those 8B/16B and lots of say, 2B or 1B in a struct (Are classes the same ?) ? I believe the same applies to simple variables even ?

I could use the '#pragma pack(1)' (I think it's MSVC specific though) to ensure no padding is fit but that would make the whole programming experience within that program to be a layer much closer to assembly (because I would need to control/check/test every single variable) wouldn't it ?

Also, you did mention 8Bytes or more likely 16Bytes will work almost for anything, but the example code of allocating "sizeof(T)" will allocate appropriate space for it, how does it deal with the fact that the class object would be 16 Bytes, say, having 3 ints and 4 chars ? Would it just be fine with an 8Byte alignment because it will read data members one by one and will pad 4 zero Bytes to each int as well as 7 zero Bytes to chars ?

Additionally, I did not find a "aligned_alloc" (nor it's very visible on google straight off) as was mentioned by Hodgman.

### #14Bregma  Crossbones+   -  Reputation: 3512

Like
1Likes
Like

Posted 29 September 2013 - 07:06 PM

You cannot allocate memory with "new[]" without creating the objects and calling their constructors unless "placement new" is used.

It sounds to me more like you don't understand the difference between placement new and ::operator new.  You're use of the phrase "calling the constructor" and the way you distinguish between object creation, memory allocation, and the constructors and the way you originally didn't understand about copy constructors would lead me to think that getting a good grasp on basic object life cycle should come before using crufty corners of the language to reimplement what the standard library does on the basis of premature microoptimization.

Sure, it's fun but it's ultimately unproductive and generally leads to the false belief that C++ is error-prone and hard to use.

Stephen M. Webb
Professional Free Software Developer

### #15RoundPotato  Members   -  Reputation: 82

Like
-1Likes
Like

Posted 29 September 2013 - 09:08 PM

You cannot allocate memory with "new[]" without creating the objects and calling their constructors unless "placement new" is used.

It sounds to me more like you don't understand the difference between placement new and ::operator new.  You're use of the phrase "calling the constructor" and the way you distinguish between object creation, memory allocation, and the constructors and the way you originally didn't understand about copy constructors would lead me to think that getting a good grasp on basic object life cycle should come before using crufty corners of the language to reimplement what the standard library does on the basis of premature microoptimization.

Sure, it's fun but it's ultimately unproductive and generally leads to the false belief that C++ is error-prone and hard to use.

Yes, you are partially right, I didn't even knew what ::operator new was until I read it.

I withdraw my statement, as it is actually possible to allocate memory using it.

However I see the advice as non-relevant due to this:

Allocates size bytes of storage, suitably aligned to represent any object of that size

Which makes sense if you pass the size of one Object, it will allocate space for it properly aligned for it.

So one could conclude that if you pass sizeof(SomeObject*5) (with the intention of allocating space for 5 SomeObjects) it will allocate that space suitably aligned for any object of that size ... which is five times that of SomeObject which is not what is wanted.

A suitable example is presented for ::operator new[] ( third example under the Example header). However it's definition is identical which leaves me hanging in confusion... as I would not want an alignment for arrays of objects, rather an Object alone used within those arrays... right... ?

At the same time there is this which makes me wonder the difference between malloc and new.

Edited by RoundPotato, 29 September 2013 - 09:20 PM.

### #16ultramailman  Prime Members   -  Reputation: 1125

Like
0Likes
Like

Posted 29 September 2013 - 10:11 PM

I don't think it's good to use malloc with objects in c++. If you want to pre-allocate a fixed chunk of memory, consider using new[] POD objects.

You cannot allocate memory with "new[]" without creating the objects and calling their constructors unless "placement new" is used. Unless you mean some "new char[]" which doesn't sound like it's much better in regards to alignment I have no idea what would that use.

What I mean is making your objects POD. That way your objects won't have any constructors or destructors to call; new[] will only allocate memory. I think that's a good way to go if you must pre-allocate memory.

### #17Hodgman  Moderators   -  Reputation: 19620

Like
2Likes
Like

Posted 29 September 2013 - 10:22 PM

I could use the '#pragma pack(1)' (I think it's MSVC specific though) to ensure no padding is fit but that would make the whole programming experience within that program to be a layer much closer to assembly (because I would need to control/check/test every single variable) wouldn't it ?

No... Don't do that.
#pragma pack(1)
struct
{
char a; short b; int c;
} data;
data.c = data.b = data.a = 42;
printf( "%d", data.c );
What kind of assembly would you use to implement that? Would you use bit-shifting and masking operations? Unaligned load and stores? Do you have to load multiple loads into a few registers, then shift, mask and OR them together to reconstruct the variable that straddles two different aligned-words?

The compiler puts in padding for a good reason -- it makes the generated assembly code much simpler.

Isn't both 8B and 16B alignments "heart stabbing" when you might have only one or a few occurrences of those 8B/16B and lots of say, 2B or 1B in a struct (Are classes the same ?) ? I believe the same applies to simple variables even ?

I don't get the "heart stabbing" phrase; is it a Lithuanian saying?
The compiler will insert the minimum amount of padding to ensure that each variable is correctly aligned.
Yes, classes and structs are the same thing.
//     \/ alignment requirement for the struct itself
struct a1 { char a,b,c,d; } //no padding
struct a4 { int a,b,c; } // no padding
struct a8 { double a,b,c,d; } //no padding
struct a8 { double a; int b,c; }//no padding
struct a8 { double a; int b; char _pad_[4]; }//first member requires 8B alignment, round up structure size to a multiple of 8
struct a4 { int a; short b; char c; char _pad_; }//first member requires 4B alignment, round up structure size to a multiple of 4
struct a4 { short a; char _pad_[2]; int b; }//second member requires 4B alignment, insert 2 padding bytes before it so that it is aligned
struct a2 { char a; char _pad_; short b; }//second member requires 2B alignment, insert 1 padding byte before it so that it is aligned
It's a good rule of thumb to declare your struct members form largest to smallest, to minimize padding:
struct {
double a, b, c;
int d, e;
short f;
char g;
char _pad_;//the struct requires 8B alignment, pad size up to a multiple of 8

struct {
int d;
double a, b;
short f;
int d, e;
char g;
double c;
}//13 bytes of padding total!

the class object would be 16 Bytes, say, having 3 ints and 4 chars ? Would it just be fine with an 8Byte alignment because it will read data members one by one and will pad 4 zero Bytes to each int as well as 7 zero Bytes to chars ?

struct { int a,b,c; char d,e,f,g; };
The int members require 4B alignment and the chars require 1B alignment. The class alignment is max(4,1), or 4B. 8B will also work, because it's a multiple of 4. There will be no padding, because as long as the class itself is 4B aligned, then all the members will be aligned.

The second example uses the vector which is overhead for something which should be simple.
low-details that affect performance, I actually need to pre-allocate memory for dynamic object creation with manually creating each object there, so I need only memory nothing more.

With all the debugging features disabled, and when used correctly, the overhead of a std::vector is about 8 bytes of space, and zero performance (when compared to the same operations performed manually). What's even better, is that their use of manual construction/destruction is fully tested and debugged.
Regarding performance, you should generally go with the easy to read/write/maintain solution first, and then complicate it with an optimized version if it is demonstrated to be necessary.

The overhead of iterating over your array checking an embedded active flag (as in your other thread) is likely going to be a much bigger performance pitfall.
If you make a post about the actual problem you're trying to solve (a pool allocator?), you'll get some good solutions, rather than just a schooling on alignment and exotic new flavours

Edited by Hodgman, 29 September 2013 - 10:39 PM.

### #18RoundPotato  Members   -  Reputation: 82

Like
0Likes
Like

Posted 30 September 2013 - 09:51 AM

I don't get the "heart stabbing" phrase; is it a Lithuanian saying?

Not sure why or how Lithuania relates. But I thought the phrase was obvious, my apologies, I meant "isn't this very wasteful?!", surely one would ask that, when a declared char for 1 Byte could get padded up to 8 Bytes instead.
I might suspect that from your statement:

The compiler puts in padding for a good reason -- it makes the generated assembly code much simpler.

That is all about the CPU versus memory trade-off and CPU wins over the memory consumption ? (...by far ?)

The compiler will insert the minimum amount of padding to ensure that each variable is correctly aligned.
Yes, classes and structs are the same thing.

//     \/ alignment requirement for the struct itself
struct a1 { char a,b,c,d; } //no padding
...
It's a good rule of thumb to declare your struct members form largest to smallest, to minimize padding:
struct {
double a, b, c;
int d, e;
...
struct { int a,b,c; char d,e,f,g; };
The int members require 4B alignment and the chars require 1B alignment. The class alignment is max(4,1), or 4B. 8B will also work, because it's a multiple of 4. There will be no padding, because as long as the class itself is 4B aligned, then all the members will be aligned.

So what you are saying is:
1) The members in a structure/class that follow a member of highest size will be padded or grouped(they are grouped right?) into an alignment.
2) The members in a structure/class that stand before a member of the highest size will not be grouped but will be padded to the size of that member.

Did I understand that correctly ?

If you make a post about the actual problem you're trying to solve (a pool allocator?), you'll get some good solutions, rather than just a schooling on alignment and exotic new flavours

I am processing my thoughts and the knowledge I receive and make examples, solutions to which will help me evolve and master certain concepts I have in mind.

Trust me, the very detailed replies you give me (and you have my gratitude for having so much patience with me) are of immense help, and prove a lot more useful than a particular solution to a particular problem.

Edited by RoundPotato, 30 September 2013 - 09:53 AM.

### #19rip-off  Moderators   -  Reputation: 6250

Like
0Likes
Like

Posted 30 September 2013 - 10:11 AM

If your program has a bottleneck that you can prove is related to padding, you probably have enough data to seriously consider a structure-of-arrays approach, rather than the usual array-of-structures.

That said, this thread is wandering off topic, and the discussion is getting rather advanced given this thread is in For Beginners.

### #20RoundPotato  Members   -  Reputation: 82

Like
0Likes
Like

Posted 30 September 2013 - 10:22 AM

If your program has a bottleneck that you can prove is related to padding, you probably have enough data to seriously consider a structure-of-arrays approach, rather than the usual array-of-structures.

If what I understood in my post above is true then I can see where you are coming from, otherwise I don't since I'm not entirely sure.

That said, this thread is wandering off topic, and the discussion is getting rather advanced given this thread is in For Beginners.

I'm sorry, I am a beginner to some concepts(even though while not to others) and as you can probably tell, I do ask beginner questions such as allocating memory, what and how is alignment and others. In the process of this thread I have learned quite a lot including about existence of "temporary objects" which part of my first post was about.

I just hope to get my final questions answered and be off to implementing what I deducted/processed. I do feel like I could make a minimum of 3 or 4 new threads with questions from this post, and if you believe that is appropriate please tell me and I'll do so since I'm not sure.

Edited by RoundPotato, 30 September 2013 - 10:22 AM.

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS