Community
cancel
Showing results for 
Search instead for 
Did you mean: 
SergeyKostrov
Valued Contributor II
434 Views

Aligned C++ objects created with a 'new' C++ operator

This is a new thread related to aligned memory management C++ operators 'new' / 'delete' and 'new[]' / 'delete[]'.

Please take a look at a similar thread:

Forum topic: 'Aligning with new: for a beginner'
Web-link: http://software.intel.com/en-us/forums/topic/328019

Thanks to a User 'llevrel' for that subject!

Best regards,
Sergey

PS: This is the first post and many more will follow...

0 Kudos
24 Replies
SergeyKostrov
Valued Contributor II
422 Views

Here are source codes of my test case: [cpp] ... class CAlignedObject { public: CAlignedObject( void ) { // printf( "CAlignedObject::CAlignedObject\n" ); }; ~CAlignedObject( void ) { // printf( "CAlignedObject::~CAlignedObject\n" ); }; void * operator new( size_t nSize, size_t nAlignment ); void operator delete( void *pObject, size_t nAlignment ); }; void * CAlignedObject::operator new( size_t nSize, size_t nAlignment ) { if( ( (nAlignment)&(nAlignment-1) ) == 0 ) return ( void * )_aligned_malloc_dbg( nSize, nAlignment, __FILE__, __LINE__ ); else return ( void * )NULL; } void CAlignedObject::operator delete( void *pObject, size_t nAlignment ) { if( pObject != NULL ) _aligned_free_dbg( pObject ); } ... CAlignedObject *pAO = NULL; for( int i = 1; i <= 1024; i++ ) { pAO = new( i ) CAlignedObject(); if( pAO != NULL ) printf( "Object Aligned on %4ld - %s\n", ( int )i, ( ( int )pAO % i == 0 ) ? "Yes" : "No" ); else printf( "Alignment value %4ld is NOT a power of 2\n", ( int )i ); if( pAO != NULL ) { delete pAO; pAO = NULL; } } ... [/cpp]
SergeyKostrov
Valued Contributor II
422 Views

>>...Here are source codes of my test case . Sorry for formatting issues in the submitted test case. It's not my fault...
SergeyKostrov
Valued Contributor II
422 Views

Here are some outputs from my test case: . [ Output 1 ] ... CAlignedObject::CAlignedObject ... CAlignedObject::~CAlignedObject ... . [ Output 2 ] ... Object Aligned on 1 - Yes Object Aligned on 2 - Yes Alignment value 3 is NOT a power of 2 Object Aligned on 4 - Yes Alignment value 5 is NOT a power of 2 Alignment value 6 is NOT a power of 2 Alignment value 7 is NOT a power of 2 Object Aligned on 8 - Yes Alignment value 9 is NOT a power of 2 Alignment value 10 is NOT a power of 2 Alignment value 11 is NOT a power of 2 Alignment value 12 is NOT a power of 2 Alignment value 13 is NOT a power of 2 Alignment value 14 is NOT a power of 2 Alignment value 15 is NOT a power of 2 Object Aligned on 16 - Yes Alignment value 17 is NOT a power of 2 ... Alignment value 31 is NOT a power of 2 Object Aligned on 32 - Yes Alignment value 33 is NOT a power of 2 ... Alignment value 63 is NOT a power of 2 Object Aligned on 64 - Yes Alignment value 65 is NOT a power of 2 ... Alignment value 127 is NOT a power of 2 Object Aligned on 128 - Yes ... Object Aligned on 256 - Yes ... Object Aligned on 512 - Yes ... Alignment value 777 is NOT a power of 2 ... and so on
SergeyKostrov
Valued Contributor II
422 Views

Here is some additional information: . CRT-functions '_aligned_malloc_dbg' or '_aligned_malloc' don't allocate memory directly and use 'malloc_dbg' or 'malloc' CRT-functions: . [ For Debug configuration ] . _aligned_malloc_dbg -> _aligned_offset_malloc_dbg -> malloc_dbg . At some point it will do a verification in a '_aligned_offset_malloc_dbg' CRT-function if a value of alignment is a power of 2 using IS_2_POW_N( align ) macro of Microsoft CRT library . [ For Release configuration ] . _aligned_malloc -> _aligned_offset_malloc -> malloc . Note: Let me repeat again, in the Release configuration '_aligned_offset_malloc' CRT-function makes a call to '_aligned_offset_malloc_dbg'
SergeyKostrov
Valued Contributor II
422 Views

I had a couple of MS C/C++ compiler warnings for my test case: . warning C4291: 'void * CTestObject::operator new( size_t )' : no matching operator delete found; memory will not be freed if initialization throws an exception warning C4311: 'type cast' : pointer truncation from 'CTestObject *' to 'int' . These two warnings could be disabled with pragma directives: . #pragma warning ( disable : 4291 ) #pragma warning ( disable : 4311 )
SergeyKostrov
Valued Contributor II
422 Views

We discussed a lot of different issues in the 'Aligning with new: for a beginner' thread and after my additional investigation I have very interesting results. . Here is a summary: . - CRT-functions '_aligned_malloc_dbg' or '_aligned_malloc' could be used in a C++ operator 'new' ( so far I didn't try to use these functions in a C++ operator 'new[]' / please try by yourself if interested ) . - When CRT-functions '_aligned_malloc_dbg' or '_aligned_malloc' are used in a C++ operator 'new' a C++ object constructor will be called and object will be constructed ( about 1.5 year ago I had some problems with it / unfortunately, it is hard to recall what was wrong ) . - C++ operator 'new' allocates memory for a C++ object if alignment boundary value IS a power of 2 ( verified on a range of alignment boundary values up to 1024 ) . - C++ operator 'new' doesn't allocate memory for a C++ object if alignment boundary value is NOT a power of 2 and returns NULL ( this is by design of '_aligned_offset_malloc_dbg' CRT-function / a Release configuration '_aligned_offset_malloc' CRT-function makes a call to '_aligned_offset_malloc_dbg' (!) ) . - CRT-functions '_aligned_malloc_dbg' / '_aligned_free_dbg' or '_aligned_malloc' / '_aligned_free' are Microsoft specific ( I didn't see a similar set of functions in GCC-like or some legacy C++ compilers / MinGW or Borland C++, for example )
jimdempseyatthecove
Black Belt
422 Views

Sergey, Consider adding an ASSERT((sizeof(*this)%nAlignment) == 0); in your overloaded new. This will assure during testing that the "you" in user has properly padded the struct/class to force a size of a multiple of the alignment (this need not be a power of 2). Note, when the sizeof the struct/class (including virtual function pointers if any) is a multiple of the size of alignment then an array of the struct/class can be // in the overload for new MyClass[nElements] MyClass* array = (MyClass*)aligned_malloc(sizeof(*this)*nElements, nAlignment); if(array) { for(int i=0; i < nElements; ++i) new (&array) MyClass; // Perform the ctor at address specified } Jim Dempsey
SergeyKostrov
Valued Contributor II
422 Views

Hi Jim, ... >>...Consider adding an ASSERT((sizeof(*this)%nAlignment) == 0); in your overloaded new. This will assure during testing that the "you" in >>user has properly >>padded the struct/class to force a size of a multiple of the alignment (this need not be a power of 2)... . You are right and thank you for the note!
jimdempseyatthecove
Black Belt
422 Views

See attached file: Illustrates aligned objects with overloads for new, delete, new[], delete[], for base and derived types. Read notes relating to where and when to use padd. Code is "AS IS". Jim Dempsey *** ignore the .docx file, use the .txt file
jimdempseyatthecove
Black Belt
422 Views

*** GRIPE *** Unable to delete attache file
SergeyKostrov
Valued Contributor II
422 Views

>>...Illustrates aligned objects with overloads for new, delete, new[], delete[], for base and derived types... . Hi Jim, Thank you very much and that example looks awesome. Best regards, Sergey . PS: I've never used a __FUNCSIG__ macro because I didn't know about its existence...
SergeyKostrov
Valued Contributor II
422 Views

I'd like to make a couple of follow ups. . >>...this need not be a power of 2... . This is a limitation of '_aligned_offset_malloc_dbg' CRT-function and it always uses IS_2_POW_N( align ) macro. If somebody wants to create an object on any alignment boundary value then a new function could be created based on '_aligned_offset_malloc_dbg' CRT-function but without _VALIDATE_RETURN and IS_2_POW_N macros.
SergeyKostrov
Valued Contributor II
422 Views

>>...This is a limitation of '_aligned_offset_malloc_dbg' CRT-function and it always uses IS_2_POW_N( align ) macro... . Take a look at [ VS InstallDir ]\VC\Crt\Src\dbgheap.c if interested: [cpp] ... extern "C" _CRTIMP void * __cdecl _aligned_offset_malloc_dbg( size_t size, size_t align, size_t offset, const char * f_name, int line_n ) { uintptr_t ptr, r_ptr, t_ptr; _AlignMemBlockHdr *pHdr; /* validation section */ _VALIDATE_RETURN( IS_2_POW_N( align ), EINVAL, NULL ); ... [/cpp]
SergeyKostrov
Valued Contributor II
422 Views

Here is a different way of using the CAlignedObject class: . Note: Where N is a next power of two number that is greater than sizeof( CAlignedObject ) [cpp] ... CAlignedObject *pAO = new( N ) CAlignedObject(); ... [/cpp]
SergeyKostrov
Valued Contributor II
422 Views

>>...PS: I've never used a __FUNCSIG__ macro because I didn't know about its existence... . Jim, I have a question: Did you compile the codes with Intel and Microsoft C++ compilers? . I had some issues with the __FUNCSIG__ macro.
SergeyKostrov
Valued Contributor II
422 Views

Just discovered that . _aligned_malloc _aligned_malloc_dbg _aligned_free _aligned_free_dbg . CRT-functions are NOT supported on Windows Mobile platforms.
jimdempseyatthecove
Black Belt
422 Views

Sergey Kostrov wrote:

This is a limitation of '_aligned_offset_malloc_dbg' CRT-function and it always uses IS_2_POW_N( align ) macro. If somebody wants to create an object on any alignment boundary value then a new function could be created based on '_aligned_offset_malloc_dbg' CRT-function but without _VALIDATE_RETURN and IS_2_POW_N macros.

The size of the structure need not be a power of 2. The size of the structure needs to be a multiple of the power of 2 that you require for alignment (e.g. 8-bytes for doubles, 16 -bytes for SSE, or 32-bytes for AVX2, ...) I tested with Intel C++, I did not test with MSVC **** Potential gotcha *** In the new[] operator, the Intel compiler generates a size_t header element containing the count of the elements in the array. Thus the necessitating of creating of the prefix padd in the allocation, and the bung-up (fix-up) of the returned pointer (converse in the delete[] operator). *** this value may change from compiler vendor to compiler vendor *** Therfore it is a requirement that you run a verification program, such as the provided test program, then make adjustments (conditional compilations) as required. You will note that you will need to do this in any event because the VTable information may vary from vendor to vendor. You might consider keeping a verification test in the beginning of the program in the event that a library function (.DLL, .so) returns the new[]. The information (diagnostic) may be more helpful than a GP fault in determining the problem. Jim Dempsey
jimdempseyatthecove
Black Belt
422 Views

Sergey Kostrov wrote:

Just discovered that
.
_aligned_malloc
_aligned_malloc_dbg
_aligned_free
_aligned_free_dbg
.
CRT-functions are NOT supported on Windows Mobile platforms.

It should be easy enough to overload the missing funcitons. Jim Dempsey
SergeyKostrov
Valued Contributor II
422 Views

>>>>>>...PS: I've never used a __FUNCSIG__ macro because I didn't know about its existence... >>>> >>>>Jim, I have a question: Did you compile the codes with Intel and Microsoft C++ compilers? >>>> >>>>I had some issues with the __FUNCSIG__ macro. >> >>I tested with Intel C++, I did not test with MSVC I see. Thanks, Jim. Issues with __FUNCSIG__ macro are detected when I tried to use that macro in a project that has UNICODE support. I'll provide more technical details later.
jimdempseyatthecove
Black Belt
90 Views

Sergey, part of the requirements of using an "AS-IS" program example is working out the peculiarities of your compiler+options, typically by use of conditional compile directives. We've probably carried this thread far enough. Code revisions should likely be maintained on some suitable site (sourceforge, stackoverflow, etc...). Thanks for your contributions. Jim Dempsey
Reply