views:

219

answers:

7

1)
For which datatypes must I allocate memory with malloc?

  • For types like structs, pointers, except basic datatypes, like int
  • For all types?

2)
Why can I run this code? Why does it not crash? I assumed that I need to allocate memory for the struct first.

#include <stdio.h>
#include <stdlib.h>

typedef unsigned int uint32;
typedef struct 
{
  int a;
  uint32* b;
}
foo;

int main(int argc, char* argv[])
{
 foo foo2;
 foo2.a = 3;
 foo2.b = (uint32*)malloc(sizeof(uint32));
 *foo2.b = 123;
}

Wouldn't it be better to use

foo* foo2 = malloc(sizeof(foo));

3) How is foo.b set? Does is reference random memory or NULL?

#include <stdio.h>
#include <stdlib.h>

typedef unsigned int uint32;
typedef struct 
{
  int a;
  uint32* b;
}
foo;

int main(int argc, char* argv[])
{
 foo foo2;
 foo2.a = 3;

}
+1  A: 

You can do it, but this is not enough.

Because, the second field is a pointer, which has to be set to a valid address. One of the ways to do it is by allocating memory (with malloc).

To your first question - use malloc when you MUST manage object's lifetime manually.

For instance, the second code could be rewritten as:

int main(int argc, char* argv[])
{
 foo foo2; uint32 b;
 foo2.a = 3;
 foo2.b = &b;
 *foo2.b = 123;
}

This is better, because lifetime is the same, and the memory is now on stack - and doesn't need to be freed.

Pavel Radzivilovsky
+6  A: 

Edit to address your numbered questions.

  1. There are no data types you must allocate with malloc. Only if you want a pointer type to point to valid memory must you use the unary & (address-of) operator or malloc() or some related function.

  2. There is nothing wrong with your code - the line:

    foo foo2;
    

    Allocates a structure on the stack - then everything works as normal. Structures are no different in this sense than any other variable. It's not better or worse to use automatic variables (stack allocation) or globals or malloc(), they're all different, with different semantics and different reasons to choose them.

  3. In your example in #3, foo2.b's value is undefined. Any automatic variable has an undefined and indeterminate value until you explicitly initialize it.

Carl Norum
+2  A: 

foo foo2; automatically allocates the structure on the stack, and it is automatically deallocated when the enclosing function (main in this case) ends.

You only need to allocate memory on the heap, using malloc, if you need the structure to persist after the enclosing scope ends. You may also need to do this when the object is too large to fit on the stack.

casablanca
+1  A: 

The memory for the struct instance ("foo2") will be allocated on the stack - there's no need to allocate memory for this yourself - if you do allocate using malloc be sure to free off the memory at a later date.

Will A
+13  A: 

All types in C can be allocated either dynamically, automatically (on the stack) or statically. The issue is not the type, but the lifetime you want - you use malloc when you want an object to exist outside of the scope of the function that created it, or when you don't know in advance how big a thing you need.

anon
+1: C99 allows the use of stack allocation for variable length structures (well, arrays, but that's enough to do everything). But I don't recommend it for anything significant anyway; in practice, the stack tends to be *much* smaller than the heap. (I also work a lot with code where the data structure lifetime does not match the stack frame lifetime.)
Donal Fellows
+3  A: 

You must allocate with malloc any memory that you wish to be managed manually, as opposed to automatically. It doesn't matter if what's stored there is an int or a double or a struct or anything; malloc is all about manual memory management.

When you create a variable without malloc, it is stored on the stack and when it falls out of scope, its memory is automatically reclaimed. A variable falls out of scope when the variable is no longer accessible; e.g. when the block or function that the variable was declared in ends.

When you allocate memory with malloc, it is stored on the heap, and malloc returns a pointer to this memory. This memory will not be reclaimed until you call free on it, regardless of whether or not a pointer to it remains accessible (when no pointers remain to heap-allocated memory, this is a memory leak). This means that you gain the ability to continue to use the memory you allocated after the block or function that it was allocated in ends, but on the other hand you now have the responsibility to manually deallocate it when you are finished with it.

In your example, foo2 is on the stack, and will be automatically deallocated when main ends. However, the memory pointed to by foo2.b will not be automatically deallocated, since it is on the heap. This isn't a problem in your example because all memory is returned to the OS when the program ends, but if it were in a function other than main it would have been a memory leak.

Tyler McHenry
+2  A: 

2) Why can I run this code? Why does it not crash?

The code never refers to undefined memory or NULL. Why would it crash? (You have a memory leak as written, but it's probably because you're only showing part of the code and in the given program it's not a problem anyway.)

The alternative code you suggest will also work, though memory returned from malloc is also uninitialized by default. (I once worked with a custom memory allocator that filled returned memory blocks with ? characters by default. Still perfectly legal by the rules. Note that calloc returns a pointer to zero-initialized memory; use it if that's what you want.)

3) How is foo.b set? Does is reference random memory or NULL?

Random memory. Stack allocated structures are not initialized for you.

Donal Fellows