0

the problem is I can't free it,the console output pointer are the same inside free function, the xcode detected at the line from function StringList_add when realloc called.

typedef struct stringlist_s {
        int max_str;
        char **str;
}stringlist_t;

//functions
stringlist_t *StringList_new()
{
    stringlist_t *lst = (stringlist_t *)malloc(sizeof(stringlist_t));

    return lst;
}

void StringList_add(stringlist_t *str_list,char *str)
{
    if(!str)
        return;
    if(!str_list)
        return;

    str_list->str = (char **)realloc(str_list->str, sizeof(char *)  * (str_list->max_str+1));

    str_list->str[str_list->max_str] = (char *)malloc(strlen(str) + 1);

    memcpy(str_list->str[str_list->max_str], str, strlen(str) + 1);

    str_list->max_str++;
}

void StringList_release(stringlist_t *strList)
{
    if(!strList) {
        printf("Releasing empty pointer\n");
         return;
    }

    for(int i = 0 ; i < strList->max_str; ++i )
    {
        free(strList->str[i]);
        printf("pointer inside is %p\n",strList->str[i]);
    }

    printf("list before is  %p\n",strList);
    free(strList);
    printf("list  now is %p\n",strList);  //value is the same as previous printf

}

I just use this to test the code above:

stringList_t *a = StringList_new();
StringList_add(a,"abc");
StringList_add(a,"edf");
StringList_release(a);
2
  • Use valgrind and gdb to debug your memory leak, or else use Boehm's conservative garbage collector (i.e. replace malloc by GC_malloc etc.) Commented Oct 16, 2012 at 17:57
  • printf("list now is %p\n",strList); //value is the same as previous printf, that's normal, freeing a pointer doesn't usually change the address the pointer points to, you just mustn't dereference it between the free and pointing it to some valid memory. Commented Oct 16, 2012 at 18:06

1 Answer 1

4

A problem is that StringList_new() allocates a new stringList_t but never initialises it members. At the call to realloc():

str_list->str = (char **)realloc(str_list->str, sizeof(char *)  * 
    (str_list->max_str+1));

neither str_list->str or str_list->max_str have been initialised. From the reference page for realloc():

It must be previously allocated by malloc(), calloc() or realloc() and not yet freed with free(), otherwise, the results are undefined.

which will be the case when used with an unitialised pointer.

Change to:

stringlist_t *StringList_new()
{
    stringlist_t *lst = malloc(sizeof(*lst));
    lst->max_str = 0;
    lst->str     = NULL;

    return lst;
}

Don't cast the return value of malloc() or realloc(). Passing a NULL pointer to realloc() is fine, it behaves like malloc() in that case. When using realloc() store the return value in a temporary pointer variable to avoid a memory leak in the event that realloc() fails:

char** tmp = realloc(str_list->str, sizeof(*tmp)  * (str_list->max_str+1));
if (tmp)
{
    str_list->str = tmp;
}

Note I did not use calloc() in StringList_new() as according the C standard all bits zero need not represent a null pointer.

Sign up to request clarification or add additional context in comments.

1 Comment

sorry max_str is just a typo,it should be int not int *, about str I did realloc it later,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.