4

I am a beginner in C. Below is my scenario - I have created a pointer variable in main function and it has been passed on to several functions(in this example 2 levels). And one of the functions frees it up. Now I need to have check in Main to see whether the pointer is freed or not, that means i need to setup the value of &str in main() to point to NULL. Not sure my approach is right here. Any help would be much appreciated

void func2(char *str)   
{
    free(str); 
}

void func1(char *str)
{
   func2(str); 
}

int main()
{ 
   char *str;
   str=(char *) malloc(10);
   func1(str);
   if(str){ do something; }  // if condition to check whether str is freed 
}
M.M
  • 138,810
  • 21
  • 208
  • 365
Hipster1206
  • 411
  • 6
  • 13
  • 4
    There is no possible way you can check for that. This is what makes manual memory management hard. – milleniumbug Jun 20 '14 at 03:59
  • of course there is... and it is quite simple once you understand how to use pointers. – nightshade Jun 20 '14 at 04:11
  • You can do this (not sure why @milleniumbug says otherwise) with a few changes, but do you really want to? This is a poor design in general. Memory management in C largely revolves around ownership. Try to keep clear who owns what memory as much as possible and you'll have far fewer problems. – Ed S. Jun 20 '14 at 04:15
  • 2
    BTW, [Don't cast malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – M.M Jun 20 '14 at 04:32
  • @EdS. Ok, apparently I haven't read the context - question title asks "How to check if a pointer has been freed?" and my comment is accurate here (well, you can't do that), and the rest of the question (sans the code) asks a different question "How to mark a pointer as NULL outside of the function?" – milleniumbug Jun 20 '14 at 11:53
  • @milleniumbug: You're 100% correct if you take the title at face value, but if you read the question you can see that he is trying to assign a sentinel value (NULL) to indicate whether or not the pointer has been freed. The OP simply doesn't understand how variables are passed around in C. – Ed S. Jun 20 '14 at 21:09

5 Answers5

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

func2(char **str)
{
        free(*str);                //free
        *str = NULL;               //Set to NULL
}

func1(char **str)                   //func1 receives as **
{
        func2(str);                //Pass pointer to func2()
}

int main()
{
        char *str = NULL;
        str=(char *) malloc(10);
        func1(&str);                //Pass Address of pointer to func1()

        if(str)                     //Check for NULL
        {
                printf("\n Not - Freed...\n");
        }
        else
        {
                printf("\n Freed...\n");
        }                                             
        return 0;
}

In C all are pass by value. I suggest to study http://www.cs.fsu.edu/~myers/cgs4406/notes/pointers.html for understanding of this.

Jeyaram
  • 9,158
  • 7
  • 41
  • 63
  • You dont need to be creating pointer to pointer to ... to pointer... once you sent the address of str in func1 you already have its address, doesn't matter if you are passing a copy of it to th next 500 function calls, the address is the same and you will be changing str by dereferencing with a single * – nightshade Jun 20 '14 at 04:27
  • @nightshade Right. Updated. – Jeyaram Jun 20 '14 at 04:30
1

You could try something like this - first redefine malloc and free (track.h)

#ifndef track_h
#define track_h
extern void* trackmalloc(size_t size);
extern void trackfree(void* array);
extern void trackismalloc(void* array);
#define malloc trackmalloc
#define free trackfree

#endif

Then for every piece of code that uses malloc and free, replace #include with #include "track.h"

#include <stdlib.h>
#include <stdio.h>
#include "track.h" /* was <malloc.h> */

// A function which has a 20% chance of freeing the pointer
void twentypercent(char* array)
{
    if (rand() < (RAND_MAX / 5))
        free(array);
}


int main(int argc, char* argv[])
{
    char* list = malloc(256);
    int ii;

    for (ii = 0; ii < 10; ++ii)
        twentypercent(list);

    if (trackismalloc(list)
        printf("Not freed yet");

    return 0;
}

Now define track.c. This will only free memory that has been allocated by by trackmalloc. If it was not allocated by trackmalloc, then it will report that the memory has already been freed.

#include <stdio.h>
#include <malloc.h>
#define TRACKER_MAX 2048
static void* tracker[TRACKER_MAX] = { 0 };
static int track_last = -1;
void* trackmalloc(size_t size)
{
    // For simplicity, tracker will not be reused
    tracker[++track_last] = malloc(size);
    return tracker[track_last];
}

void trackfree(void* array)
{
    // This will slow down as the list gets filled up.
    // You will need a more efficient way of searching lists (possibly bsearch)
    int tt;
    for (tt = 0; tt < track_last; ++tt)
    {
        if (array == tracker[tt])
        {
            free(tracker[tt]);
            tracker[tt] = 0;
            break;
        }
    }

    if (tt == track_last)
        printf("%p already freed\n", array);
}

int trackismalloc(void* array)
{
    // This will slow down as the list gets filled up.
    // You will need a more efficient way of searching lists (possibly bsearch)
    int tt, result = 0;
    for (tt = 0; tt < track_last; ++tt)
    {
        if (array == tracker[tt])
        {
            result = 1;
            break;
        }
    }
    return result;
}
cup
  • 7,589
  • 4
  • 19
  • 42
0
void func1(char** str) {
    free(*str);
    *str = NULL;
}

void func2(char** str) {
    free(*str);
    *str = NULL;
}

int main() {
    char *str;

    str = (char*) malloc(10);
    func1(&str);
    if (str) {
        do something;
    }
}
0
void func2(char **str)   
{
    free(*str); 
    *str = 0;
}

void func1(char **str)
{
   func2(str); 
}

int main()
{ 
   char *str;
   // I'd recommend using sizeof(type_you_want) * amount_of_elements instead of
   // a constant number: ->  malloc(sizeof(char) * 10);

   str=(char *) malloc(10);

   func1(&str); // You must pass the address of the pointer, because you want
               // to change "WHAT IT POINTS TO", not "WHAT IS POINTED BY IT"

   if(str){ do something; }  // if condition to check whether str is freed 
}

When you call a function in C, you pass a copy of those arguments, so you are passing a copy of that pointer (that copy still points to the same place, so you can change that place that it points to) but you want to change the pointer value, so you need to pass its address.

I have explained a little bit how pointers inside functions can be used in here

Community
  • 1
  • 1
nightshade
  • 638
  • 5
  • 15
0
#include <stdio.h>
#include <stdlib.h>

void func2(char **str)
{
    printf("%d %s\n",__LINE__,__func__);
    free(*str);
    *str = NULL;
}

void func1(char **str)
{
    printf("%d %s\n",__LINE__,__func__);
    func2(str);
}

char * allocaMem(char **ptr)
{
    *ptr=(char *) malloc(sizeof(char)* 10);
    if(!*ptr)
    {
        perror("");
    }
    else
    {
        return *ptr;
    }
}

int main()
{
    char *str = allocaMem(&str);
    if (!str) {
        printf("Error in malloc()\n");
        return -1;
    }

    func1(&str);

    if (str) {
        printf("Memory Not freed\n");
    } else {
        printf("Memory freed\n");
    }
}
SD.
  • 1,432
  • 22
  • 38