Jump to content
  • Advertisement
Sign in to follow this  
tharris997

Memory alignment

This topic is 3588 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm working on a simple memory manager for debugging purposes. One of the things I'm doing is writing a custom ::operator new that adds an allocation header to any memory allocated on the heap. This is being done to gather metrics, but mostly to track memory leaks. However, I have some concerns about memory alignment. In C++ what I'm doing looks something like this:
void* operator new(std::size_t uiSize)
{
    std::size_t newSize = uiSize + sizeof(AllocationHeader);
    void* pMem = malloc(newSize);
    AllocationHeader* pHeader = pMem;
    // Fill out allocation header data here
    void* pObjectMemBlock = pMem + sizeof(AllocationHeader);
    return pObjectMemBlock; 
}

My concern is that the returned pObjectMemBlock may not be aligned properly, because I'm not returning the aligned pMem returned by malloc but rather an address part way into that block. Now I assume that I can solve the problem by padding AllocationHeader to a certain size. Unfortunately I'm not sure what size. I'm working on several different platforms too, so I may need to align differently for each platform. Those platforms are: *Intel Core 2 Duo under WinXP *AMD Athlon 4800+ under WinXP *Intel Celeron Dual Core under Ubuntu *Intel based MacBook under OSX These can all be considered x86 architecture, right? I've heard though that Linux machines barf on misaligned memory though. is that right? Anyway, if anyone can tell me how I should pad AllocationHeader that'd be great! Incidentally, I'm aware that x86 machines can generally handle misaligned memory at a performance cost. Although I'll only be using this code for debug builds, I'd still prefer everything be aligned correctly. Cheers!

Share this post


Link to post
Share on other sites
Advertisement
As you are aware, x86 handles unaligned memory accesses perfectly fine at a slight performance hit. This is true regardless of operating system.

Typically, alignment would be 8-bytes on a 32-bit architecture, and 16-bytes on a 64-bit architecture. I'd say that just aligning to a 16-byte boundary is a pretty safe bet.

Share this post


Link to post
Share on other sites
Just add max_alignment-the_size_of_whatever_you_add to realign it.

The problem is that malloc is often broken and doesn't provide the max alignment as it should.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sc4Freak
Typically, alignment would be 8-bytes on a 32-bit architecture, and 16-bytes on a 64-bit architecture. I'd say that just aligning to a 16-byte boundary is a pretty safe bet.


Just curious, where do you get that information from? I thought it was typically equal to the system's word size.

Share this post


Link to post
Share on other sites
Quote:
Original post by loufoque
Just add max_alignment-the_size_of_whatever_you_add to realign it.

The problem is that malloc is often broken and doesn't provide the max alignment as it should.


I'm unfamiliar with max_alignment and can't find it in any of the standard headers. Where is it usually defined? FYI I'm using GNU compiler & libs.

Thanks!

Share this post


Link to post
Share on other sites
Funnily enough, now that I've looked more closely, sizeof(AllocationHeader) seems to already be doing the alignment work for me. No matter the size of the structure, it always returns a value that's a multiple of 8. I wonder if it would return multiples of 16 on a 64-bit architecture?

Thanks for the help guys :)

Share this post


Link to post
Share on other sites
Quote:
Original post by loufoque
The problem is that malloc is often broken and doesn't provide the max alignment as it should.
On what platform? Win32 and GCC both guarantee it to be 8 bytes on 32 bit platforms and 16 bytes on 64.

You are correct that you need to handle alignment yourself. If you know that you are only going to compile a 32bit binary then you can safely add some padding to your AllocationHeader to force it to be a multiple of 8 bytes. This will keep you consistent with the usual alignment for new.

Share this post


Link to post
Share on other sites
Does your AllocationHeader have a member that is 8 bytes? That would make the compiler pad the structure. Unless one of the types in the structure change size the size should stay the same on 64-bit.

Share this post


Link to post
Share on other sites
The padding appears to occur on all platforms, but I'm using GCC on all too. So if it guarantees 8 bit alignment on 32 bit platforms then that would make sense.

I'll add padding anyway to guarantee 8 byte alignment (and 16 if I ever build for 64-bit) because I like to cover all bases. However, if I'm only building with GCC this isn't strictly necessary, right? As I said, I'll do it all the same because I prefer to write robust code that will hold up if circumstances change down the line (e.g. different compiler).

Oh and Wolfdog, at present the AllocationHeader I'm using is only 6 bytes total but gets padded to 8 all the same.

Cheers!

Share this post


Link to post
Share on other sites
Quote:
Original post by tharris997
The padding appears to occur on all platforms, but I'm using GCC on all too. So if it guarantees 8 byte alignment on 32 bit platforms then that would make sense.

I'll add padding anyway to guarantee 8 byte alignment (and 16 if I ever build for 64-bit) because I like to cover all bases. However, if I'm only building with GCC this isn't strictly necessary, right? As I said, I'll do it all the same because I prefer to write robust code that will hold up if circumstances change down the line (e.g. different compiler).


You should be good with what you mentioned earlier, but adding support for 64bit doesn't hurt.

Quote:
Oh and Wolfdog, at present the AllocationHeader I'm using is only 6 bytes total but gets padded to 8 all the same.

The compiler will pad a structure for proper alignment of its members, so you probably have a 4 byte member in there that is causing the padding to a multiple of 4. Not sure about the 8 byte padding unless you have an 8 byte member.

You can use this assertion to check the alignment:
Assert((*((int*)&pObjectMemBlock) & ~7) == *((int*)&pObjectMemBlock),"Bad alignment.");

replace the 7 with 15 for 64bit, and of course you would need a 64 bit type to hold the pointer.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!