What Exactly Is an 'Aligned Pointer'

Pointer alignment

This is a good one too - Data_structure_alignment

A memory address a, is said to be
n-byte aligned when n is a power of
two and a is a multiple of n bytes. In
this context a byte is the smallest
unit of memory access, i.e. each
memory address specifies a different
byte. An n-byte aligned address would
have log2 n least-significant zeros
when expressed in binary.

What's the purpose of align C++ pointer position

Some platforms require certain types of data to appear on certain byte boundaries (e.g:- some compilers
require pointers to be stored on 4-byte boundaries).

This is called alignment, and it calls for extra padding within, and possibly at the end of, the object's data.

Compiler might break in case they didn't find proper alignment OR there could be performance bottleneck in reading that data ( as there would be a need to read two blocks for getting same data).

EDITED IN RESPONSE TO COMMENT:-

Memory request by a program is generally handled by memory allocator. One such memory allocator is fixed-size allocator. Fixed size allocation return chunks of specified size even if requested memory is less than that particular size. So, with that background let me try to explain what's going on here:-

uchar* udata = (uchar*)malloc(size + sizeof(void*) + CV_MALLOC_ALIGN);

This would allocate amount of memory which is equal to memory_requested + random_size. Here random_size is filling up the gap to make it fit for size specified for fixed allocation scheme.

uchar** adata = alignPtr((uchar**)udata + 1, CV_MALLOC_ALIGN);

This is trying to align pointer to specific boundary as explained above.

Correct way for pointer alignment

A pointer is aligned if your quotient is 0 after performing modulo operation pointer mod alignment.

This means that you can check (in C++11) using

#include <cstdint>
bool isAligned = ((reinterpret_cast<std::uintptr_t>(pointer) % alignment) == 0);

You can also do it using bitwise operation (only if alignment is a power of 2)

bool isAligned = ((reinterpret_cast<std::uintptr_t>(pointer) & (alignment - 1)) == 0);

However, the compiler will probably optimize that for you.

How to free aligned pointer?

If the pointer (and possibly the alignment size) is your only information, you'd need to store some kind of metadata (the original pointer, alignment offset etc.) somewhere. It might be before your allocated memory block, which you can then access when performing the deallocation, or some registry (e.g. hashtable or map) somewhere else, where you will store the metadata and retrieve them according to the address when de-allocating.

One possible (oversimplified) implementation (not tested, just for illustration - in the real case, the stored value will also need to be aligned properly, if align is smaller than the suitable alignment for uintptr_t):

void* allocate_align_1(size_t size, uintptr_t align)
{
void* addr = malloc(size + align + sizeof(uintptr_t));

uintptr_t aligned_addr = (uintptr_t)addr + sizeof(uintptr_t);
aligned_addr += align - (aligned_addr % align);

// store the original address
*(uintptr_t*)(aligned_addr - sizeof(uintptr_t)) = (uintptr_t)addr;

return (void*)aligned_addr;
}

Then in deallocate, you can access the data (for proper use there could/should be some check of a guard value or similar to make sure the correct data is really there), an example without checking:

void deallocate(void * ptr)
{
uintptr_t orig_ptr = *(uintptr_t*)((uintptr_t)ptr - sizeof(uintptr_t));
free((void*)orig_ptr);
}

What is a misaligned pointer?

Many architectures have a concept called alignment where the hardware is designed to operate on addresses that are multiples of the word size. For example, on a 32-bit processor, objects might be aligned to 32-bit boundaries (4 bytes), and on a 64-bit processor, objects might be aligned to 64-bit boundaries (8 bytes). An aligned pointer is one that points to an address that's a multiple of the word size, and an unaligned pointer is one that's not pointing to an address that's a multiple of the word size.

On most architectures, reading or writing unaligned pointers suffers some sort of penalty. On some processors, doing this causes a bus error, which usually terminates the program immediately. On others, such as x86, unaligned reads and writes are legal but suffer a performance penalty due to how the hardware is structured.

In your code, 0xFFFFFFFF = 232 - 1 is probably not aligned, since it's not a multiple of most common word sizes (it's not divisible by any power of two other than 20).

Hope this helps!

Do 4byte aligned pointers use any padding?

You may notice the key word "usually" in that statement. "Usually" does not imply "always". And if something isn't always true, you can't assume it to be true and just chop off the last two bits.

Most pointers to live objects will have alignments of at least 4 bytes. However, you can create an array of chars, and those elements will be byte addressable. That something happens 99% of the time doesn't mean you can ignore the final 1% where it doesn't happen.

The reason why most pointers are aligned to at least 4 bytes is that most pointers are pointers to objects or basic types that themselves are aligned to at least 4 bytes. Things that have 4 byte alignment include (for most systems): int, float, bool (yes, really), any pointer type, and any basic type their size or larger.

Any object that contains one of these must be aligned to at least the alignment of that object. So an object that stores an int is aligned to 4 bytes. An object that contains a pointer is aligned to at least 4 bytes. And so forth. Rare is the object that doesn't include one of these basic types.

That's why. The vast majority of data types you want to point to will have a minimum of 4 bytes of alignment.



Related Topics



Leave a reply



Submit