25

I've heard that malloc() aligns memory based on the type that is being allocated. For example, from the book Understanding and Using C Pointers:

The memory allocated will be aligned according to the pointer's data type. Fore example, a four-byte integer would be allocated on an address boundary evenly divisible by four.

If I follow, this means that int *integer=malloc(sizeof(int)); will be allocated on an address boundary evenly divisible by four. Even without casting (int *) on malloc.

I was working on a chat server; I read of a similar effect with structs.

And I have to ask: logically, why does it matter what the address boundary itself is divisible on? What's wrong with allocating a group of memory to the tune of n*sizeof(int) using an integer on address 129?

I know how pointer arithmetic works *(integer+1), but I can't work out the importance of boundaries...

Misha Brukman
  • 12,938
  • 4
  • 61
  • 78
user1833028
  • 865
  • 1
  • 9
  • 18
  • 3
    I can confirm, the book does misleadingly say, verbatim: *Dynamic memory is allocated from the heap. [...] However, the memory allocated will be aligned according to the pointer's data type.* – cnicutar May 09 '14 at 23:46
  • See here: http://www.gamedev.net/page/resources/_/technical/general-programming/c-custom-memory-allocation-r3010 It sort of goes a little bit into why alignment is important and choice of allocators. Games utilize performance to the best of a computer's ability most of the time and as such, I think it is a good idea to look at that article a bit.. Look at the `Aligned Allocations` section. Near the very end, it also shows benchmarks. – Brandon May 10 '14 at 01:47
  • There also exist CPUs that will emit a hardware trap if you attempt to dereference an unaligned pointer to a 32-bit int (sparc, I'm looking at you...). – Andre Kostur May 10 '14 at 02:33
  • 5
    Without knowing what the standard says, you can tell immediately that something is amiss with that statement. Think about what a call to malloc() looks like: malloc() has *no way* to know the type of the pointer. – Euro Micelli May 10 '14 at 03:22
  • Heh, yeah you're right. The statement may be true about c++'s operator "new", but not malloc. malloc has to assume the worst. – Don Hatch May 10 '14 at 10:03
  • Oh wait, now I'm thinking twice about that. Pretending we don't know what the standard says, and trying to imagine a world in which the book is correct and makes sense (which is where I imagine user1833028 was coming from with the question)... for example if you call malloc(3), then malloc *does* know something about the type of pointer, in some cases... it knows it's not a pointer to something of size 4 or multiple thereof; in fact it would be within reason for its contract to allow it to assume the pointed-to type is not even a multiple of 2, i.e. no alignment needed at all in this case. – Don Hatch May 10 '14 at 10:47

6 Answers6

28

The memory allocated will be aligned according to the pointer's data type.

If you are talking about malloc, this is false. malloc doesn't care what you do with the data and will allocate memory aligned to fit the most stringent native type of the implementation.

From the standard:

The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated)

And:

Logically, why does it matter what the address boundary itself is divisible on

Due to the workings of the underlying machine, accessing unaligned data might be more expensive (e.g. x86) or illegal (e.g. arm). This lets the hardware take shortcuts that improve performance / simplify implementation.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
11

In many processors, data that isn't aligned will cause a "trap" or "exception" (this is a different form of exception than those understood by the C++ compiler. Even on processors that don't trap when data isn't aligned, it is typically slower (twice as slow, for example) when the data is not correctly aligned. So it's in the compiler's/runtime library's best interest to ensure that things are nicely aligned.

And by the way, malloc (typically) doesn't know what you are allocating. Insteat, malloc will align ALL data, no matter what size it is, to some suitable boundary that is "good enough" for general data-access - typically 8 or 16 bytes in modern OS/processor combinations, 4 bytes in older systems.

This is because malloc won't know if you do char* p = malloc(1000); or double* p = malloc(1000);, so it has to assume you are storing double or whatever is the item with the largest alignment requirement.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
4

The importance of alignment is not a language issue but a hardware issue. Some machines are incapable of reading a data value that is not properly aligned. Others can do it but do so less efficiently, e.g., requiring two reads to read one misaligned value.

ooga
  • 15,423
  • 2
  • 20
  • 21
  • This is the most correct answer. I add 1) that malloc has no knowledge of the type of data referenced by the pointer. Malloc cannot tell if it is allocating a pointer to 2 2-byte integers or 1 4-byte integer. 2) Malloc implementations often use interlocked instructions for thread safety. These usually require aligned data. – user3344003 May 10 '14 at 01:26
  • @user3344003 The answers that tell you the claim is false are all more correct than this one, which only tells you why it would be true if it was true, which it isn't. – user207421 May 11 '14 at 04:15
  • @EJP Your comment makes no sense. I was answering his main question "why does it matter what the address boundary itself is divisible on?" I.e., why is alignment important. I wasn't saying anything at all about malloc (and the fact that is must allocate to the most stringent alignment since it knows nothing about the data type). – ooga May 11 '14 at 04:23
  • The key points are 1) Some processors cannot access unaligned data and 2) most other processors are inefficient if they do. Ooga got both in a concise answer to why malloc cares. The question is wrong in asserting that malloc does this based upon the return type. – user3344003 May 11 '14 at 17:52
4

The book quote is wrong; the memory returned by malloc is guaranteed to be aligned correctly for any type. Even if you write char *ch = malloc(37);, it is still aligned for int or any other type.

You seem to be asking "What is alignment?" If so, there are several questions on SO about this already, e.g. here, or a good explanation from IBM here.

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
2

It depends on the hardware. Even assuming int is 32 bits, malloc(sizeof(int)) could return an address divisible by 1, 2, or 4. Different processors handle unaligned access differently.

Processors don't read directly from RAM any more, that's too slow (it takes hundreds of cycles). So when they do grab RAM, they grab it in big chunks, like 64 bytes at a time. If your address isn't aligned, the 4-byte integer might straddle two 64-byte cache lines, so your processor has to do two loads and fix up the result. Or maybe the engineers decided that building the hardware to fix up unaligned loads isn't necessary, so the processor signals an exception: either your program crashes, or the operating system catches the exception and fixes up the operation (hundreds of wasted cycles).

Aligning addresses means your program plays nicely with hardware.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
0

Because it's more fast; Most processor likes data which is aligned. Even, Some processor CANNOT access data which is not aligned! (If you try to access this data, processor may occur fault)

ikh
  • 10,119
  • 1
  • 31
  • 70
  • can you give me example of processor that will fail on non aligned data? But give me something 1980+ – Nick Jan 22 '15 at 18:52
  • 1
    @Nick Don't find in old things; [ARM is one of this processors.](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0301h/Babceedc.html) – ikh Jan 24 '15 at 02:09
  • thanks. I think I tried it and was OK, but will check it again and will update here. I have gcc packed structures and they works for sure. – Nick Jan 24 '15 at 16:40
  • just checked it on samsung cpu. created char x[1000], then put int * on & x[1]. Value was read correctly. Not sure if ARM CPU handled it or gcc did the value reconstruction, but it worked. – Nick Jan 24 '15 at 16:51