Thread: malloc alignment

  1. #1
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305

    malloc alignment

    I have been tinkering around with this program but i am still unable to understand it. This is supposed to allocate memory returned my malloc and align it to a 4 byte boundary. I got this from the net but i have a lot of questions about it.

    [insert]
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    /* align_size has to be a power of two !! */
    void *aligned_malloc(size_t size, size_t align_size) {
    
      char *ptr,*ptr2,*aligned_ptr;
      int align_mask = align_size - 1; // what is this for and why i am subtracting -1 from it.
      ptr=(char *)malloc(size + align_size + sizeof(int)); // i allocate 72 bytes though i want only 4 bytes
      if(ptr==NULL) return(NULL);
    
      ptr2 = ptr + sizeof(int); // why adding sizeof(int) to it  aligned_ptr = ptr2 + (align_size - ((size_t)ptr2 & align_mask)); // this one goes above my head
      ptr2 = aligned_ptr - sizeof(int); // why??????
      *((int *)ptr2)=(int)(aligned_ptr - ptr); // for what reason ?????
    
      return(aligned_ptr);
    }
    
    void aligned_free(void *ptr) {
    
      int *ptr2=(int *)ptr - 1;
      ptr = (int *)ptr - *ptr2;
      free(ptr);
    }
    
    int main( void )
    {
        // declare the type of data pointer that
        // we want to allocate...
        char* pData = 0;
    
        pData = aligned_malloc( 64, 4 ); // let's get 64 bytes aligned on a 4-byte boundry
    
        if( pData != NULL )
        {
            ; // do something with our allocated memory
    
            // free it...
            aligned_free( pData );
            pData = 0;
        }
        return 0;
    }
    Any insights why those things have been done would be appreciated.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You need to store some extra information, hence the extra size. In your example, you want 64 bytes and the initial memory must be a multiple of 4, that is, in binary it must end with 00. Your align_mask is not-at-all-coincidentally 11 in binary (i.e. it has 1's where you must have zeroes). You then allocate 4+3+64=71 bytes (assuming 4-byte ints for example purposes). That extra int that we have will live at the front, hence moving the sizeof(int) in advance. Let's suppose that malloc comes back with 0x735; adding the 4 gives us 0x739. That means that our address in binary ends with 1001. But that's bad -- we'll have to move forward three bytes for alignment purposes. Guess what -- adding align_size (4) minus the (mask & address) expression (1) gives 3 -- the exact value we need to move forward.

    You can show, if you think about it, that 3 is the most we can need to move forward (in the case of 4-byte alignment).

  3. #3
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    Yes that makes it a lot clearer. So if instead i wish to have a alignment on a 16 bit boundary all those parameters would change accordingly. But another of the questions is that when i am trying to align it on a 4byte boundary would not allocating just 4extra bytes instead of 8 would also suffice?

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You will always need to store the int at the front (which contains the offset to get from the aligned pointer back to the original pointer from malloc). You will always need to get (x-1) bytes of padding to force the alignment to x bytes.

  5. #5
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    [insert]
    Code:
    void aligned_free(void *ptr) {
    
      int *ptr2=(int *)ptr - 1;
      ptr = (int *)ptr - *ptr2;
      free(ptr);
    }
    Okay so one more stuff that i need to clarify is that there is some corruption occuring in the heap when it comes to this routine.

    Also if my interpretation is not wrong as you said that the first integer contains the offset is this the reason why the first line is there?

  6. #6
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    Any insights ?

  7. #7
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Take a look at this thread that discussed exactly the same issue.

  8. #8
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    Thanks, now i can explain that to anyone :-).

  9. #9
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    and here's my 2c for obtaining 64 bytes aligned on a 4 byte boundary:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void *am(size_t size, size_t al)
    {
        char *ap, *mp;
        unsigned r;
    
        if (!(mp = (char *) malloc(size + al)))
            return NULL;
        printf("malloc returns %p\n", mp);
    
        r = (unsigned) mp % al;
        ap = mp + (al - r);
        *(ap - 1) = al - r;
    
        return ((void *) ap);
    }
    
    void fm(void *ap)
    {
        char *t = (char *) ap;
        char *mp = t - (unsigned char) *(t - 1);
        printf("free receives %p\n", mp);
        free(mp);
    }
    
    int main()
    {
        char *ap = (char *) am(64, 4);
        printf("aligned_ptr at %p\n", ap);
        fm((void *) ap);
    }

  10. #10
    Registered User
    Join Date
    Jun 2009
    Location
    US of A
    Posts
    305
    Extra work for me Now i have to understand this as well (Just kidding) Let me go through it and ill also try to come up with something unique of my own.

  11. #11
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by roaan View Post
    Extra work for me Now i have to understand this as well (Just kidding) Let me go through it and ill also try to come up with something unique of my own.
    Yep! because the code you got from the net doesn't work for two reasons.
    One of them is this line of code ptr = (int *)ptr - *ptr2 inside aligned_free().
    And free() receives a pointer which isn't the same that malloc() returned, causing a memory leak.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. alignment in malloc
    By cangel in forum C Programming
    Replies: 7
    Last Post: 11-03-2008, 02:04 PM
  2. How to guarantee alignment with malloc and or new?
    By mynickmynick in forum C++ Programming
    Replies: 16
    Last Post: 08-27-2008, 02:49 AM
  3. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  4. Is there a limit on the number of malloc calls ?
    By krissy in forum Windows Programming
    Replies: 3
    Last Post: 03-19-2006, 12:26 PM
  5. malloc invalid address alignment
    By code2big in forum C Programming
    Replies: 15
    Last Post: 05-25-2004, 12:25 PM