Thread: Understanding malloc and realloc functions

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    48

    Understanding malloc and realloc functions

    Hi everyone, i want to create a dynamic array using malloc and realloc functions, but i just can't understand how they work. I wrote some code to figure it out, and after seeing how this little program worked, i have some doubts.

    Here's the code:

    Code:
    int main(int argc, char *argv[])
    {
      int *myarray;
      
      myarray = malloc ( sizeof ( int ) * 3 );
      
      myarray[0] = 20;
      myarray[1] = 21;
      myarray[2] = 22;
      
      int i;
      
      for ( i = 0 ; i < 3 ; i++ )
      {
            printf ( "&#37;i\n" , myarray[i] );      
      }
      
      myarray= realloc ( myarray , sizeof ( int ) * 1 );
      myarray[5] = 25;
      
      printf ( "%i\n" , myarray[5] );
      
      system("PAUSE");	
      return 0;
    }
    This program shows in the screen the following string:

    20
    21
    22
    25

    wich is not ok. There are things in the code that i just don't get it. When i use malloc function, i'm declaring that myarray will have only three elements. Then i assign a value for each of these. After that, i show them in the screen, doing a loop. Then, with realloc function i determine that now myarray will have only one element. But, why C compiler just let me to assign a value to an element wich is supposed to not exist?. It's not supposed to erase all elements except the first?. Even if i didn't call realloc function, and added a new element to myarray wich its index was greater than two (remember that i apparently declared an array with three elements), c compiler would let me assign a value for it too. Doesn't malloc reserve a contiguous space of memory specified in bytes by its param?, if it does, why i can simply add an arbitrary number of elements, occupying all memory i want, without limits, without errors and without exceptions?.
    I hope you can help me on this guys.
    Thanks in advance.
    Regards.
    Last edited by mariano_donati; 02-17-2008 at 11:39 PM.

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    realloc receives new size (not additions)
    so if you want to store myarray[5]
    new size should be at least

    6 * sizeof(int)

    PS. Aslo read FAQ about correct usage of realloc - you should store the result in temp var in case the realloc failed
    and only if the return value is not null - assign it to the old pointer
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by mariano_donati View Post
    But, why C compiler just let me to assign a value to an element wich is supposed to not exist?.
    It's up to the programmer to know not to do things which are specified as undefined behavior.

    Quote Originally Posted by mariano_donati View Post
    Doesn't malloc reserve a contiguous space of memory specified in bytes by its param?
    At least that, I would speculate. Perhaps memory managers, for performance reasons, allocate more.

    Bottom line is that the standard says anything can happen if you break the rules. Appearing to be correct is one such possibility; don't rely on it.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  4. #4
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    I think that i haven't explained myself very well. What i meant was that even i don't resize my array (so it has three elements), i can storage myarray[any_integer].

  5. #5
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by mariano_donati View Post
    I think that i haven't explained myself very well. What i meant was that even i don't resize my array (so it has three elements), i can storage myarray[any_integer].
    As Dave said - it is undefined behavior - anything can happen... Crash for example
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  6. #6
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    Well, now i can understand a little more about how to work with them, but it requires to have a total control on the array i create, and it's not possible if i don't know how many elements it does have. How do i know an array size?

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    It is you who allocated the array, How you do not know the size?
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    Yes, but let's say that my code has two fases: one, when i allocate and reallocate the array; two, when i use this array from a function. In this function, i need to know how many elements have been set in the array to iterate on them.

  9. #9
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    pass the array size as a parameter

    or do a struct
    Code:
    struct array
    {
       int* values;
       size_t size;
    };
    and use this struct
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  10. #10
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    Thanks vart. I was just thinking about passing as a param, but i just didn't know how, and there is my answer. Thank you both for helping me out.
    Regards.

  11. #11
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I don't know if I would use a struct for an array type in C. One reason is that vart's solution, is only the tip of the iceburg. What if you needed an array of doubles for example and can't reasonably rely on redefining all or part of struct array?

    Not to say that there isn't a place for such abstraction, but it's all very dependant on what you know and what is necessarry here.

    The language provides the data structure and you can build a better interface easily with functions. You can easily manage the size yourself. If you don't know functions I guess now is the time to learn. You pass the size as a parameter like you said.

    void foo( bar * array, size_t count );

  12. #12
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by mariano_donati View Post
    I think that i haven't explained myself very well. What i meant was that even i don't resize my array (so it has three elements), i can storage myarray[any_integer].
    No you can't...

    If a bridge says it has a 4000 kilogram limit, would you expect it to collapse if a truck went across weighing 4010 kilograms? No, hopefully it wouldn't. However I guess there's a remote chance that it would. Now would it collapse if a 20000 kilogram truck went across? I'd say it probably would.

    So you overwrote your array by a few bytes. Will this crash your program? Perhaps not, but if you're unlucky it might. If you access an element 10000 places past the end of the array will it crash? Yes it probably will.

    The moral of the story is that you should not exceed the specifications. If you asked for space for 3 ints, then if you try and use any more than that your program might croak!
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  13. #13
    Registered User
    Join Date
    Nov 2007
    Posts
    48
    of course not, you're right. You guys are better than 100 books (exaggerating) i bought to learn C.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Also, consider that realloc may not actually reduce the size if the allocation, it may just mark that you have reduced the size - perhaps only actually remove the unused memory when there is a "squeeze".

    It may also decide, rather arbitrarily, that a certain size change is necessary before it does the resize itself. E.g. make malloc always allocate multiples of 128 bytes, and if you resize within the same multiple of 128 bytes, realloc doesn't reasize - if the change means more or less number of 128 byte blocks, then it actually changes the size of the allocation. 128 is of course just one possible number.

    Or realloc may allocate at "2^n" sizes, so when you grow a block for 256 to 257 bytes, it allocates 512 bytes for you to use. Then it "knows" that you have up to 512 bytes before it needs to grow again - likewise, if you shrink from 511 down to 257, it doesn't change anything, it just records that 257 bytes are used. Go from 257 to 256 bytes, and it frees the current block and allocates one that is 256 bytes long instead.

    The above ideas are just my imagination of possible "optimizations behind the scenes" for the realloc use-cases where applications reallocate in ways that are pathological - such as the word-processing app that reads a byte at a time and reallocs for every single byte it goes over the limit.

    And as stated, the hardware usually works in blocks of 4KB, and if you don't go over a 4KB limit with an out-of-bounds access, all that's going to happen is that something will be overwritten - it may not be anything important [particularly if realloc doesn't actually do anything when you shrink the allocation]. In the Windows debug modes, there is a kernel option to allocate new blocks in it's own 4KB section, and to do so at the end of the block - specifically to find when you overwrite the end of the buffer. But this is not available to normal applications, only kernel drivers and such like.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by matsp View Post
    And as stated, the hardware usually works in blocks of 4KB, and if you don't go over a 4KB limit with an out-of-bounds access, all that's going to happen is that something will be overwritten - it may not be anything important [particularly if realloc doesn't actually do anything when you shrink the allocation]. In the Windows debug modes, there is a kernel option to allocate new blocks in it's own 4KB section, and to do so at the end of the block - specifically to find when you overwrite the end of the buffer. But this is not available to normal applications, only kernel drivers and such like.
    Actually, you can use page-heap-allocation to force an immediate access violation upon buffer overflow, when writing to heap memory in your programs on Windows. It gives you a very useful crash-dump!
    I forget the registry key, but we made our own tool at work which our testers use to turn this on for specific programs. We typically have it set to only 20&#37; of allocations or some such percentage because otherwise you chew up memory pretty fast. But even that helps bring some bugs to the light.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. malloc, realloc..wat on earth!
    By zesty in forum C Programming
    Replies: 3
    Last Post: 12-21-2007, 01:42 PM
  2. To malloc or not realloc on struct members
    By gh0st in forum C Programming
    Replies: 4
    Last Post: 11-17-2006, 05:27 AM
  3. malloc, realloc
    By figo2476 in forum C Programming
    Replies: 3
    Last Post: 04-28-2006, 10:11 PM
  4. malloc and realloc
    By odysseus.lost in forum C Programming
    Replies: 3
    Last Post: 05-27-2005, 08:44 AM
  5. Need help on malloc and realloc
    By YevGenius in forum C Programming
    Replies: 8
    Last Post: 03-06-2004, 01:55 AM