When should I use malloc in C and when don't I?

73,955

Solution 1

char *some_memory = "Hello World";

is creating a pointer to a string constant. That means the string "Hello World" will be somewhere in the read-only part of the memory and you just have a pointer to it. You can use the string as read-only. You cannot make changes to it. Example:

some_memory[0] = 'h';

Is asking for trouble.

On the other hand

some_memory = (char *)malloc(size_to_allocate);

is allocating a char array ( a variable) and some_memory points to that allocated memory. Now this array is both read and write. You can now do:

some_memory[0] = 'h';

and the array contents change to "hello World"

Solution 2

For that exact example, malloc is of little use.

The primary reason malloc is needed is when you have data that must have a lifetime that is different from code scope. Your code calls malloc in one routine, stores the pointer somewhere and eventually calls free in a different routine.

A secondary reason is that C has no way of knowing whether there is enough space left on the stack for an allocation. If your code needs to be 100% robust, it is safer to use malloc because then your code can know the allocation failed and handle it.

Solution 3

malloc is a wonderful tool for allocating, reallocating and freeing memory at runtime, compared to static declarations like your hello world example, which are processed at compile-time and thus cannot be changed in size.

Malloc is therefore always useful when you deal with arbitrary sized data, like reading file contents or dealing with sockets and you're not aware of the length of the data to process.

Of course, in a trivial example like the one you gave, malloc is not the magical "right tool for the right job", but for more complex cases ( creating an arbitrary sized array at runtime for example ), it is the only way to go.

Solution 4

If you don't know the exact size of the memory you need to use, you need dynamic allocation (malloc). An example might be when a user opens a file in your application. You will need to read the file's contents into memory, but of course you don't know the file's size in advance, since the user selects the file on the spot, at runtime. So basically you need malloc when you don't know the size of the data you're working with in advance. At least that's one of the main reasons for using malloc. In your example with a simple string that you already know the size of at compile time (plus you don't want to modify it), it doesn't make much sense to dynamically allocate that.


Slightly off-topic, but... you have to be very careful not to create memory leaks when using malloc. Consider this code:

int do_something() {
    uint8_t* someMemory = (uint8_t*)malloc(1024);

    // Do some stuff

    if ( /* some error occured */ ) return -1;

    // Do some other stuff

    free(someMemory);
    return result;
}

Do you see what's wrong with this code? There's a conditional return statement between malloc and free. It might seem okay at first, but think about it. If there's an error, you're going to return without freeing the memory you allocated. This is a common source of memory leaks.

Of course this is a very simple example, and it's very easy to see the mistake here, but imagine hundreds of lines of code littered with pointers, mallocs, frees, and all kinds of error handling. Things can get really messy really fast. This is one of the reasons I much prefer modern C++ over C in applicable cases, but that's a whole nother topic.

So whenever you use malloc, always make sure your memory is as likely to be freed as possible.

Solution 5

char *some_memory = "Hello World";
sprintf(some_memory, "Goodbye...");

is illegal, string literals are const.

This will allocate a 12-byte char array on the stack or globally (depending on where it's declared).

char some_memory[] = "Hello World";

If you want to leave room for further manipulation, you can specify that the array should be sized larger. (Please don't put 1MB on the stack, though.)

#define LINE_LEN 80

char some_memory[LINE_LEN] = "Hello World";
strcpy(some_memory, "Goodbye, sad world...");
printf("%s\n", some_memory);
Share:
73,955
bignay2000
Author by

bignay2000

Updated on April 25, 2020

Comments

  • bignay2000
    bignay2000 about 4 years

    I understand how malloc() works. My question is, I'll see things like this:

    #define A_MEGABYTE (1024 * 1024)
    
    char *some_memory;
    size_t size_to_allocate = A_MEGABYTE;
    some_memory = (char *)malloc(size_to_allocate);
    sprintf(some_memory, "Hello World");
    printf("%s\n", some_memory);
    free(some_memory);
    

    I omitted error checking for the sake of brevity. My question is, can't you just do the above by initializing a pointer to some static storage in memory? perhaps:

    char *some_memory = "Hello World";
    

    At what point do you actually need to allocate the memory yourself instead of declaring/initializing the values you need to retain?

  • bignay2000
    bignay2000 over 14 years
    Just to clarify, as much as I like this answer (I did give you +1), you can do the same without malloc() by just using a character array. Something like: char some_memory[] = "Hello"; some_memory[0] = 'W'; will also work.
  • Bob Murphy
    Bob Murphy over 14 years
    Memory life cycles, and the related question of when and how to deallocate it, are an important issue with many common libraries and software components. They typically have a well-documented rule: "If you pass a pointer to this one of my routines, you need to have malloc'd it. I'll keep track of it, and free it when I'm done with it." A common source of nasty bugs is to pass a pointer to statically allocated memory to such a library. When the library tries to free() it, the program crashes. I recently spent a lot of time fixing a bug like that which someone else wrote.
  • codaddict
    codaddict over 14 years
    Your are right. You can do that. When you use malloc() the memory is dynamically allocated at run time, so you need not fix array size at compile time also u can make it grow or shrink using realloc() None of these things can be done when you do: char some_memory[] = "Hello"; Here even though you can change the content of the array, its size is fixed. So depending on your needs you use either of the three options: 1)pointer to char const 2) dynamically allocated array 3)fixed size, compile time allocated array.
  • Till Theis
    Till Theis almost 14 years
    To emphasize it's read-only you should write const char *s = "hi"; Isn't this actually required by the standard?
  • Smith Will Suffice
    Smith Will Suffice over 10 years
    Are you saying that the only time that malloc() is used practically, is when there is a segment of code that will be called multiple times during the program life that will be called multiple times and need to be 'cleaned out', since malloc() is accompanied by free()? For instance, in a game like wheel of fortune, where after you guess, and put the input in a designated char array, that the malloc()-sized array can be freed for the next guess?
  • Rob11311
    Rob11311 almost 10 years
    @Till, no because you declared a pointer initialised to the base address of string literal "hi". s can be re-assigned perfectly legally to point to a non-const char. If you want a constant pointer to a read only string, you need const char const* s;
  • Rob11311
    Rob11311 almost 10 years
    The lifetime of the data is indeed the real reason to use malloc. Supose an abstract data type is represented by a module, it declares a List type, and routines to add/delete items from the list. Those item values, need copying into dynamically allocated memory.
  • Rob11311
    Rob11311 almost 10 years
    @Bob: those nasty bugs, make the convention that the allocator frees memory far superior, after all you may be recycling it. Suppose you allocated memory with calloc to improve locality of references, that exposes the broken nature of those libraries to, because you need to call free just once for the whole block. Fortunately I've not had to use libraries which specify memory to be 'malloc-ed` it's not a POSIX tradition and would very likely be considered a bug. If they "know" you have to use malloc, why doesn't the library routine do it for you?
  • Musa Al-hassy
    Musa Al-hassy over 5 years
    Excellent example! Way to go ^_^