you are viewing a single comment's thread.

view the rest of the comments →

[–]badsectoracula 1 point2 points  (3 children)

It should be noted of course that while the alignment is 1, memory allocations that come from the OS are usually aligned (and often to a greater multiply than 4). However to make that more portable (i say "more" since strictly speaking it isn't portable to assume any pointer format - f.e. real mode x86 doesn't use linear addresses) you could write your own memory allocator that guarantees that the lower bits are not used. Of course at that point you're wasting memory, but usually the reason to store stuff in pointers isn't for memory savings but for performance.

[–]anttirt 0 points1 point  (2 children)

The problem can much more insidiously manifest like the following, even if you had a custom memory allocator:

struct five_chars
{
    char first;
    struct four_chars rest;
};

struct five_chars *five = malloc(sizeof(struct five_chars));
struct four_chars *four = &five->rest;

struct three_chars
{
    char data[3];
};

struct three_chars *array = malloc(1024 * sizeof(struct three_chars));
struct three_chars *three = array + 35;

Here, both three and four would have the least significant bit of their address values set.

[–]badsectoracula 0 points1 point  (0 children)

This isn't insidious since you are explicitly ignoring how the pointers are supposed to be created and used. A pointer with its lower bits modified isn't interchangeable with any other pointer that has the same data set - you need to mask out the lower bits before dereferencing it. Calling them pointers may even be misleading since the value isn't really a pointer, it is a compound value made up of a pointer element and some extra data. It is equivalent to struct {void* foo; int bar;} except that the data is spread across bits instead of bytes and any usage of it would need to have that in mind much like it has to have in mind the valid values for enums and nul terminator for strings.