How can I impose alignment of data wit malloc and / or new?
Guess
??Code:if (sizeof(data)%alignment) data=(data*)malloc(alignment*(sizeof(data)/alignment)+alignment) else data=(data*)malloc(sizeof(data));
With new??
How can I impose alignment of data wit malloc and / or new?
Guess
??Code:if (sizeof(data)%alignment) data=(data*)malloc(alignment*(sizeof(data)/alignment)+alignment) else data=(data*)malloc(sizeof(data));
With new??
Last edited by mynickmynick; 08-26-2008 at 07:58 AM.
The only way to guarantee alignment is by doing such alignment yourself. In new [for non-POD types], you'd have to first allocate a sufficiently large buffer and then use placement new to allocate an object in that buffer.
However, malloc() itself is guaranteed to give you an alignment to at least 8 bytes. What sort of alignment are you trying to achieve.
By the way, sizeof(data) % alignment is not meaningful - if you want to align a 128 byte structure to 128 byte alignment, that's by no means guaranteed by your test. You have to take the return value from malloc, cast it to an integer-type of sufficient size to hold an pointer and do math to check if it's aligned, and if not, align it. For 2^n alignment, you can do:
Note that you must keep the original pointer if you want to call free as well.Code:void *malloc_aligned(size_t size) { void *ptr = malloc(size + alignment-1); if (!ptr) return NULL; ptr = (void *)(((IntPtr_t)(ptr) + alignment-1) & ~alignment; }
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
What type of alignment do you require?
I've done tests with malloc previously, and it appears to me, on my Mac, that the minimum amount of storage that the system would return to be was 16 bytes, even if I requested 1 byte. And, it was always aligned to a x'10' boundary.
See this sample:
For the new operator, I expect the compiler to worry about, and properly provide for, alignment.Code:#include <stdio.h> #include <stdlib.h> int main(int argc, char* argv[]){ int i ; char * pointers[50] ; for (i = 0 ; i < 50 ; i++) { pointers[i] = malloc(i) ; printf("malloc(%d bytes) address is %p\n", i, pointers[i] ); } for (i = 0 ; i < 50 ; i++) { free(pointers[i]) ; } return 0; }
If you want other alignment, then that's easy too.
Let's say you want to obtain 4096 bytes of storage to have the address end with 3 zeros, like 45AE000. Then, get 4096 + 4095 and then round your pointer when it gets returned:
char * ptr_rounded ;
char * ptr = malloc(4096+4095) ;
ptr_rounded = ((ptr >> 3) << 3) ;
Last edited by Dino; 08-26-2008 at 08:08 AM. Reason: typo
Mainframe assembler programmer by trade. C coder when I can.
yes sorry my example was not correct at all
If you say malloc() aligns at least to 8 bytes boundaries it's enough for my multithread worries I guess. But it doesn't cope with cache matters.
For new I didn't get what happens?
Well, first of all, cache-alignment (to cache-lines) is a slightly different matter - since you then have to take into account the difference between to calls to malloc [for example MS Visual Studio .Net allocates 64-bytes apart for small objects].
I wouldn't worry about cache-line boundaries for now. [In fact, I wouldn't worry about multithread problems either because two allocations on two different threads will absolutely certainly cover more than 8 bytes of overhead anyways - except perhaps on 16-bit processors, but those won't be multicore - and probably not much of cache either, so no problem].
In the case of new, when you call new, you are asking for two things:
1. The memory to be allocated.
2. The constructor to be called.
Since the constructor is called for the original address of the data, you can't later change the pointer address and still expect things to work. To work around that, you'd have to use something called placement new, which is a call to new with a "buffer" passed to the new function for the memory to be used.
Google for "Placement new" and you'll find some information (or look it up in Stroustrup or similar - beginner C++ may not cover it).
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
Of course, that's missing a few casts, and you really need to shift 12 bits each way - or use the add/and-trick that I suggested above - the latter is probably a whole one or two clock-cycles faster - that must be, hmm, about 0.05% of the total time of malloc, so clearly worth doing ;-) [Actually, some code does this sort of thing quite a lot, such as MMU code that aligns an input address to page-boundary].
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
Yes, 12 bits. Yes, casts. That's what I get for typing off the top of my head (I was thinking 3 nibbles). Yes, AND would work just as well too. Thanks.
Mainframe assembler programmer by trade. C coder when I can.
malloc is not guaranteed to give any n of bytes alignment, but it is guaranteed to give an alignment suitable for any objects.
alignment is not guaranteed at any interval on any machine, although that is dependant on the implimentation of malloc and the memory manager library.
The only way to guarantee alignment with portable code is by manually aligning by overallocation.
on windows you can use _aligned_malloc ()
Last edited by abachler; 08-26-2008 at 07:07 PM.
As robwhit says, you should be able to allocate any type of object with correct alignment, which generally means at least 8-byte alignment (or rather, suitably aligned to the largest type of "long long", "double", "long", or "char *" [and all other standard types - but the former are most likely to be the longest])
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
Last edited by mynickmynick; 08-27-2008 at 02:26 AM.
Yes, but that is specific to glibc - which like many C libraries, have special functions that allocate aligned memory. But it's not portable to other compilers. Of course, you can hide such functions by adding your own wrapper [which may be a inline or #define macro in many cases].
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
There are two ways to achieve aligned new - placement new with a pre-aligned buffer and implement a class-specific new/delete pair. In both cases, you will be allocating memory separately, but in the class-specific new/delete you can hide the fact from a user of the classs.
--
Mats
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.