3 ms·
A pointer you get from calloc() is guaranteed to be properly aligned to not cause SIGBUS on RISCs and some such. You cannot just add random sizeof(Header) to it
by huhtenberg 11y ago
A pointer you get from calloc() is guaranteed to be properly aligned to not cause SIGBUS on RISCs and some such. You cannot just add random sizeof(Header) to it and call it a general purpose allocation. struct Header needs to be a bit more elaborate than what they have. In fact, it shouldn't be a struct, but a union -
union Header
{
var type;
max_align_t foo;
};
whereby you get max_align_t from your standard libraries or do something like this -
typedef union max_align
{
int i;
long l;
double d;
void * p;
...
} max_align_t;
- ecma 11y ago+1 - I was hunting for this to make the same point. Your Header is exactly how I would expect it to be done.
- tomp 11y agoAre you sure this is not wasteful? I always thought you could align on any word (32 bits) on a 32-bit x86 CPU, but your max_align_t would be 64 bits long (because it includes a double as well).
- huhtenberg 11y agoThat's why you should try and use standard (or compiler-specific) version of max_align_t.
- danieltillett 11y agomax_align_t is only defined in C11? Edit. Yes this looks to be the case for those of us using C99. Paul Eggert put in a patch for gnulib to cover this [1]. typedef union { char *__p; double __d; long double __ld; long int __i; } max_align_t; One thing I did learn looking through this patch was the difference NULL has in C++ and C. This is certainly not something I had ever considered. 1. https://lists.gnu.org/archive/html/bug-gnulib/2014-12/msg00170.html https://lists.gnu.org/archive/html/bug-gnulib/2014-12/msg001...
- DSMan195276 11y agoActually, you can align on any byte in x86 and it will still work, the accessing is just slower (And you loose some other guarantees). That said, lots of malloc implementations on 32-bit x86 actually return 8-byte aligned addresses, for the reason that you can have 64-bit ints and such which benefit from 8-byte alignment.
- nkurz 11y agothe accessing is just slower While there are some cases where this is an issue (writes that cross 4KB page boundaries), this generally isn't true for any x86/x64 processor made in the last decade. There may be legitimate portability reasons for avoiding unaligned access, but performance on x86 is probably not a good reason.
- DSMan195276 11y agoI generally agree with what you've said, but a performance penalty is definitely still possible by crossing a cache-line boundary - I would assume unaligned accesses are just as fast as aligned ones only when the value itself is still contained within the same cache-line. But with that said, I think you're right in that the performance here isn't really the big deal - the portability reasons alone are enough to justify making sure the returned pointer is correctly aligned.
- asveikau 11y agoAFAIK atomic reads, writes, and read-modify-write instructions still need alignment on x86.
- nkurz 11y agoGood point, although the requirement is just that they do not cross a 64B cacheline: http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf http://www.intel.com/content/dam/www/public/us/en/documents/... 8.1.1 Guaranteed Atomic Operations The P6 family processors (and newer processors since) guarantee that the following additional memory operation will always be carried out atomically: • Unaligned 16-, 32-, and 64-bit accesses to cached memory that fit within a cache line The first P6 was Pentium Pro, which came out in 1995. It does go on to say that although modern processors will guarantee atomic operations that cross cache lines, it's a bad practice that can badly hurt performance.
- asveikau 11y agoThe Windows heap functions align to 8 bytes on 32-bit. I once worked on code that depended on this. You want 8 byte alignment. For one, you could have doubles. (Though I just googled this and apparently gcc will 4 byte align those by default on x86) Another possibility is you could have a data structure that relies on "lock cmpxchg8b".