Thread: Why use malloc()

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

    Why use malloc()

    I really don't get the point of malloc. Say I have the following code:
    Code:
    	int* ptr;
    	
    	ptr = malloc(1);
    	
    	*ptr = 123456789;
    	
    	printf("%d\n", *ptr);
    	
    	free(ptr);
    This will print "123456789". Since I've only allocated one byte, why doesn't it just print "1"? Also, if I get rid of ptr = malloc(1), the code still works exactly the same. So what the heck??

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    That is very bad code. Malloc allocates memory for you to use.
    ptr might just point to some random memory that might work, but it's really, really bad design. It can just as well crash. But don't expect malloc to just allocate one byte. When allocating memory, you get lat least the number of bytes you request, but sometimes more.
    But always allocate the minimum amount of memory you need to work with - in that case, 4. Otherwise you can get unexpected results.

  3. #3
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    In this case, an accident probably saved you from yourself.

    malloc() is most likely unable or unwilling to allocate only 1 byte of memory for you, hence you are probably actually having more than that being allocated. Nevertheless, this behavior, is potentially undefined, which means if you try this on another machine, you may as well crash since an int on most modern systems is a 32-bit number, which is 4 bytes.

    Dynamically allocating memory is useful in cases where you will not know how much memory to allocate until runtime. Consider a program that has to read in an entire file and do some processing.... and assume that for whatever reason you need to have the entire file in memory, not just parts of it (although this is not always likely). How can you accomplish this? You could declare a massive array, but if you guess too small, your program can't read certain files. If you guess too large, your program wastes a substantial amount of memory. That plus arrays are limited in how big they can be on the stack.

    Hence your alternative is to attempt to allocate about as much memory as you need when you need it. That's what malloc() and free() is for.

  4. #4
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,337
    malloc() allocates data from the heap. On a Mac in OS X, the smallest amount of memory that you can get is 16 bytes, even if you ask for 1 byte. You operating system may be different. Your example just "happens" to work since your process "happens" to own the memory it is writing to.

    Todd
    Last edited by Dino; 11-26-2007 at 02:26 PM. Reason: typo

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Technically, the code you've just posted is not correct. You can't [on any ordinarily available machine] use 1 byte (the unit for malloc) and store an int - it takes 2 or 4 bytes. So correctly, you should do
    Code:
    ptr = malloc(1 * sizeof(int));
    to ask for the right amount of memory for one integer.

    It is of course a very silly example - there is no need to allocate memory at all for one integer in this example - you could just remove the star in front of ptr [and preferrably rename ptr], remove the malloc line altogether and remove the stars on assignment and printing, remove the free-line, and you'd get exactly the same result.

    But then it would not be an example of allocating memory, which I suspect it is supposed to be. If this is part of some "real" code, then it's defnitely a bad choice. This is more like the woodworking stuff you do when you start doing woodwork at school - you cut a few pieces of wood and put them together, and call it a bookend or some such - but it's really not an advanced thing, just something to teach you the basic techniques of woodworking. Same if you learn to weld or solder - you start by just attaching bits of scrap metal together, then you do more advanced stuff. Get the idea?

    --
    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.

  6. #6
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,337
    Here's an example to see for yourself on your system how much memory will be allocated.
    Code:
    #include <stdio.h>
      
    int main()
    {
    
    	int j ; 
    	char *data ; 
    	for (j = 0 ; j < 10 ; j++ ) { 
    		data = malloc(1) ; 
    		printf("Address of memory is &#37;04p\n", data) ; 
    	} 
    }
    Todd

  7. #7
    Registered User
    Join Date
    Nov 2007
    Posts
    8
    Wow, thanks for the quick replies!

    Ok, so I played around with my code a bit more and I have this now:
    Code:
    	char* ptr;
    	
    	ptr = malloc(1);
    	
    	if (ptr == NULL)
    		printf("err");
    	else
    	{
    		*ptr = "abcdefghijklmnopqrstuvwxyz-1234567890";
    	
    		printf("&#37;s\n", *ptr);
    	
    		free(ptr);
    	}
    And thank goodness it crashed. Because if that code didn't cause any errors, I would be so confused.

    So now that I'm using a c-string, how to malloc space on the fly? What do I put in the parameter for malloc?

    EDIT:
    I just want to thank you guys for the clarifications on malloc(), and that some systems allocate a min of say 4 or more bytes.
    Last edited by I-See-C; 11-26-2007 at 02:35 PM.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    That code is still just so wrong.
    You aren't assigning a string - you're assigning an adress and no, it's not just one byte long.

  9. #9
    Registered User
    Join Date
    Nov 2007
    Posts
    8
    I know it's just one byte long. That's the point. THis is just testing code, and I was wondering how I would allocate the appropriate amount of space for a c-string of x on the fly.. I'm guessing it would be malloc(x *sizeof(char))?

    And what do you mean by "You aren't assigning a string - you're assigning an adress "? I'm dereferencing the pointer to insert data, and then I dereference it again to retrieve that data and print it. What's wrong with that? What's the proper way?

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    "something" == char*
    So, *ptr = "Something" means *ptr = some_address_here;
    The real way would be strcpy for C.
    You're wrong about memory allocation too. One character takes one byte, so you need to do
    Code:
    malloc(sizeof(char) * length_of_string + 1);
    All C strings have one extra byte at the end with the value 0 that tells all functions that this is the end of the string.

    If you actually look at the assembly code, you'll see that the compiler takes the lower byte of the address of the string and puts it into ptr. In my testing, it put 0x38 there (which represents the character '8').
    Unfortunately, this kind of thing is valid code in C, but fortunately, not in C++.
    Last edited by Elysia; 11-26-2007 at 02:55 PM.

  11. #11
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    A pointer contains the address where a value is. Malloc(1) means you're allocating only one byte for a char array (!!!), which is only good for a NULL array (aka ""), because char array's length should be at least the text's length + 1 (null terminator).

    With integer values (char, short, int etc) you can use this technique to get data into the pointed address:
    Code:
    *acharptr='A'; //note that 'A' represents an integer
    *acharptr=245; //unsigned char can hold a value up to 255
    *anintegerptr=50000;
    But in case of a string (char array), it doesn't do what you want it to do. It makes the pointer point to a new location (the string you specified, hardcoded somewhere in the program memory) and means that the memory address of allocated memory gets lost, which means a memory leak.

    To get data into a buffer, you should do something like this:
    Code:
    strcpy(ptr, "abcdefghijklmnopqrstuvwxyz-1234567890");
    If you allocate memory for a char array, you MUST allocate enough bytes for the data you want to put into it. And if you don't know how long string it has to carry, then you could use a power of 2 as the length (256,512,1024 etc).
    Code:
    char *ptr;
    ptr=malloc(1024*sizeof(char));
    strcpy(ptr,"blablablabla");
    strcat(ptr,"morestuff"); //append to char array
    sprintf("string---> &#37;s",ptr); //note that %s means a char array (char*), so no *ptr here
    free(ptr);
    And if you know the length of what you want to copy there:
    Code:
    char* ptr;
    ptr=malloc((sizeof("yourstringhere")+1)*sizeof(char));
    strcpy(ptr,"yourstringhere");
    sprintf("string---> %s",ptr);
    free(ptr);
    Last edited by maxorator; 11-26-2007 at 03:06 PM.
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  12. #12
    Registered User
    Join Date
    Nov 2007
    Posts
    8
    K, so I'm trying to put a char array into a pointer. Maybe this doesn't make much sene, but yea. The following is bad code, I know that it is, but help me out.
    Code:
    	char* ptr;
    	char word[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    	int count = 0;
    	
    	ptr = malloc(sizeof(char) * strlen(word) +1);
    	
    	if (ptr == NULL)
    		printf("err");
    	else
    	{
    		//How do I copy over the char array into the pointer? This is wrong...
    		for (count=0; count<strlen(word); count++)
    			strcat(ptr, word[count]);
    		
    		printf("&#37;s\n", ptr); //this is wrong
    	
    		free(ptr);
    	}
    Last edited by I-See-C; 11-26-2007 at 03:12 PM. Reason: Changed code a bit due to maxorator's helpful post :) still not working though

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    char mystr[50];
    char* pMyStr = malloc(sizeof(char) * 50);
    strcpy(mystr, "abcdefghijklmnopqrstuvwxz");
    strcpy(pMyStr, "abcdefghijklmnopqrstuvwxz");
    free(pMyStr);
    Also beware, because strlen returns the length of strings, not including the NULL char. So when allocating memory from the length of a given string gotten from strlen, add +1 to it.

  14. #14
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    It's all very simple.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main( void )
    {
        const char * str_static = "You can give a string literal a name."; /** assigning the address of a string literal **/
        char * str_heap = malloc( strlen( "You can store a string on the heap." ) + 1 );
        if( str_heap != NULL ) {
            char str_auto[] = "You can store a string on the stack.";
    
            strcpy( str_heap, "You can store a string on the heap." );
            puts( str_auto );
            puts( str_static );
            puts( str_heap );
    
            free( str_heap );
        }
        return 0;
    }
    What does this print and why?

    When you can answer that you will understand.

  15. #15
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by I-See-C View Post
    K, so I'm trying to put a char array into a pointer. Maybe this doesn't make much sene, but yea. The following is bad code, I know that it is, but help me out.
    Code:
    	char* ptr;
    	char word[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    	int count = 0;
    	
    	ptr = malloc(sizeof(char) * strlen(word) +1);
    	
    	if (ptr == NULL)
    		printf("err");
    	else
    	{
    		//How do I copy over the char array into the pointer? This is wrong...
    		for (count=0; count<strlen(word); count++)
    			strcpy(word[count], ptr);
    		
    		printf("%s\n", *ptr); //this is wrong
    	
    		free(ptr);
    	}
    strlen won't work here, since you don't actually have a NUL at the end of your array of alphabet letters - the array only holds 26 elements, and none of those is zero. In this particular case you could use sizeof(word) - but that only works if you have a local array.

    THis is also broken:
    Code:
    strcpy(word[count], ptr);
    word[count] is a single char, and you are copying a string ptr into it - it will crash, I can guarantee it [assuming you ignore the warnings that the compiler will give for trying to pass a char as a pointer].

    --
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. malloc + segmentation fault
    By ch4 in forum C Programming
    Replies: 5
    Last Post: 04-07-2009, 03:46 PM
  2. the basics of malloc
    By nakedBallerina in forum C Programming
    Replies: 21
    Last Post: 05-20-2008, 02:32 AM
  3. 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
  4. Malloc and calloc problem!!
    By xxhimanshu in forum C Programming
    Replies: 19
    Last Post: 08-10-2005, 05:37 AM
  5. malloc() & address allocation
    By santechz in forum C Programming
    Replies: 6
    Last Post: 03-21-2005, 09:08 AM