i'm sending a NULL pointer of type unsigned char to a function. i allocate space for this pointer in the function and return nothing.

unsigned char ucBufr = NULL;
Allocation(ucBufr);
void Allocation(unsigned char * ucBufr)
{
        /* nDataSize and ucData is got from a file here. */
        ucBufr = malloc(nDataSize);
        ucBufr[0] = 'B';
        ucBufr[1] = 'U';
        memcpy(ucBufr+2,ucData,nDataSize);
        /* ... */
}

what i want to be sure is, after function statements does the allocation space dissapear? i do not get any errors, but i do not want to fall into segmentation faults further in my program. why i am asking this is because I know that after function statements local variables which are defined in the function are freed by the O/S. Could we expect the same bad event with malloc?

Thanx.

Recommended Answers

All 11 Replies

>>what i want to be sure is, after function statements does the allocation space dissapear

Yes because you sent the pointer by value and not by reference. You need to send a pointer to a pointer which requires two stars not just one.

Allocation(&ucBufr);


void Allocation(unsigned char ** ucBufr)
{
        /* nDataSize and ucData is got from a file here. */
        *ucBufr = malloc(nDataSize);
        *ucBufr[0] = 'B';
        *ucBufr[1] = 'U';
        memcpy(*ucBufr+2,ucData,nDataSize);
        /* ... */
}

>>local variables which are defined in the function are freed by the O/S
The OS does not do that for local variables but it will for memory allocated by malloc() -- local variables are freed by the program itself when the function returns to its caller and cleans up the stack.

I haven't programmed a lot of C but to the best of my knowledge:

unsigned char ucBufr = NULL;

1. This is not a null pointer, it's a char variable (1 byte set to 0).

>I know that after function statements local variables which are defined in the function are freed by the O/S

Not quite. Primitive types (int, char, etc) go on the stack and fall of when the function returns. Pointers and References however, live on the stack themselves, but the value they point to/reference is a memory address on the heap. These you must explicitly free before the function returns, otherwise when the pointer/reference falls of the stack allocated memory is lost or leeked as it's commonly known.

Ah thanks Ancient Dragon now we know.

> *ucBufr[0] = 'B';
Or even (*ucBufr)[0] = 'B'; You mean to index into where the pointer points to, not index your (pointer to a pointer), then dereference.

Yes OS supposed to free all the memory allocated by the program when the program exits. But nevertheless, it's a good habbit to free all allocated space when no longer needed, because the program may later be changed in a way that memory would be repeatedly allocated, and the amount of unused allocated memory would constantly increase when we forgot to free it. The failure to free the allocated space when no longer needed, is called memory leak. This may happen when we forget to free the memory, or when we are not able to do it, because we for some reason lost the pointer pointing to the allocated memory, as was the case above. Memory leak is harmful because it may cause the amount of memory allocated by the program to increase without control while the program runs. This may easily become serious when we allocate large amounts of memory or allocate frequently (in fact, some systems never allocate less than some 4 kb page at a time), everything may happen fast, and sometimes may well be possible that our program allocates all the available memory in the system, even if we have a gigabyte of memory.

what i want to be sure is, after function statements does the allocation space dissapear?

No, it doesn't. But you _do_ lose the only reference to the space you had, and that's called a memory leak because now it's allocated and won't be freed until the program ends. If your OS doesn't free all memory allocated to a process when it's done, the memory won't be freed until you reboot.

In your program you'll get an exception on top of the memory leak because outside the function ucBufr will still be null. That's because when you passed the pointer to Allocation, it made a copy of the pointer to allocate memory to. When the function returns, that pointer is lost and the original ucBufr is still what it was before.

Your function just takes a pointer and allocates memory to it so you don't need to use a parameter at all. You should make the pointer in the function and then return it so you don't have to use double pointers to keep from losing the reference.

unsigned char *Allocation( void ) {
  unsigned char *ucBufr;

  /* nDataSize and ucData is got from a file here. */
  ucBufr = malloc( nDataSize );
  ucBufr[0] = 'B';
  ucBufr[1] = 'U';
  memcpy( ucBufr + 2, ucData, nDataSize );
  /* ... */

  return ucBufr;
}

after function statements local variables which are defined in the function are freed by the O/S.

Local variables aren't freed after a function returns. What happens is that all of the stuff for a function is pushed onto the runtime stack before the instructions for the function are run. That's called a stack frame, and it holds stuff like the return address, arguments, and local variables. That way the instructions use the stack and everything looks like execution jumped into the function.

When the function returns, the stack frame is popped off of the stack, but popping off the stack doesn't free any memory. All it does is move the stack pointer down by the number of bytes the stack frame occupied. All of the stuff is still there, you just don't have access to it anymore and the next thing that gets pushed onto the stack will overwrite it.

Could we expect the same bad event with malloc?

malloc doesn't use the stack, it uses the heap. As long as the pointer that's on the stack doesn't go out of scope (when a local variable goes out of scope it gets popped off the stack) or you have another pointer in scope that points to the memory, you won't lose it. If you lose all references to some memory, you won't be able to free it. That's the bad event you should avoid with malloc. ;)

commented: Good explanation +4

I haven't programmed a lot of C but to the best of my knowledge:

unsigned char ucBufr = NULL;

1. This is not a null pointer, it's a char variable (1 byte set to 0).

>I know that after function statements local variables which are defined in the function are freed by the O/S

Not quite. Primitive types (int, char, etc) go on the stack and fall of when the function returns. Pointers and References however, live on the stack themselves, but the value they point to/reference is a memory address on the heap. These you must explicitly free before the function returns, otherwise when the pointer/reference falls of the stack allocated memory is lost or leeked as it's commonly known.

i wanted to write like this :

unsigned char * ucBufr = NULL;

what does fall of means? aren't primitive type memory allocations(not with pointer) freed by OS after function statements to make those memory locations possible to be used with other variable names further in the program?

is leaking a redundant lost memory which faces us with unrecognized segmentation faults?

what does fall of means? aren't primitive type memory allocations(not with pointer) freed by OS after function statements to make those memory locations possible to be used with other variable names further in the program?

Read Hamrick's earlier post it's far more elloquent. Where Hamrick talks about the stack pointer moving down to reach the return value of the function. Therefore, all the local variables that were pushed onto the stack on top of the return value, are now above the stack pointer in memory This means they are out of scope (no longer accessable, thrown away, fallen off, popped off)

what does fall of means?

All of the memory for the stack is preallocated. The OS allocates it when the program starts and frees it when the program ends, but while the program is running, it's all still there. Going in and out of scopes will push and pop local variables without allocating or freeing. Here's a program that simulates what happens.

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

#define STACK_SIZE 10
#define STACK_OVERFLOW 0
#define STACK_UNDERFLOW 1
#define STACK_SUCCESS 2

static int stack[STACK_SIZE];
static int top = 0;

// Push a new integer onto the stack and return its address
static int new_int( int **value ) {
  if ( top == STACK_SIZE ) {
    return STACK_OVERFLOW;
  }

  *value = &stack[top++];

  return STACK_SUCCESS;
}

// Pop the first N integers off of the stack
static int free_ints( int n ) {
  if ( top - n < 0 ) {
    return STACK_UNDERFLOW;
  }

  top -= n;

  return STACK_SUCCESS;
}

void process_values( int **values, int size ) {
  int i;

  // Create a few new integers
  for ( i = 0; i < size; ++i ) {
    if ( new_int( &values[i] ) != STACK_OVERFLOW ) {
      *values[i] = ( i + 1 ) * 10;
    } else {
      fprintf( stderr, "Stack overflow!\n" );
      exit( EXIT_FAILURE );
    }
  }

  // Show their values
  for ( i = 0; i < size; ++i ) {
    printf( "Value #%d = %d\n", i + 1, *values[i] );
  }

  printf( "\n" );

  // Remove them from the stack
  if ( free_ints( size ) == STACK_UNDERFLOW ) {
    fprintf( stderr, "Stack underflow!\n" );
    exit( EXIT_FAILURE );
  }
}

int main( void ) {
  int *values[5];
  int i;

  // Process values once
  process_values( values, sizeof values / sizeof( int ) );

  // Clear the values to get an accurate test
  for ( i = 0; i < sizeof values / sizeof( int ); ++i ) {
    values[i] = NULL;
  }

  // Do it again to see that the stack was preserved
  process_values( values, sizeof values / sizeof( int ) );

  return 0;
}

is leaking a redundant lost memory which faces us with unrecognized segmentation faults?

Leaking memory doesn't cause an exception unless you run out of memory and get a system halt. ;) The problem with leaking memory is that it allocates memory and doesn't free it so you use up all of the fast memory and dig into the virtual memory. That slows everything on the computer down.

process_values( values, sizeof values / sizeof( int ) );

Consider

process_values( values, sizeof values / sizeof *values );

If you're going to the trouble to use sizeof() to determine how many elements are in an array, why not use sizeof(*array) to get the size of each element in the array instead of hard-coding in the variable type?

It's sort of like

int *p = malloc(10 * sizeof(int));

versus

int *p = malloc(10 * sizeof(*p));

...

sizeof(*variable) is a constant expression, so it's not like it's any less efficient.

why not use sizeof(*array) to get the size of each element in the array instead of hard-coding in the variable type?

Because I didn't know I could do that. ;) That's a good idea, but I'm not worried about the type since it's pretty much not going to change. I was using that sizeof trick to get the number of cells in the array. Thanks for the tip though. I'll be sure to use it in the future. :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.