justastranger
justastranger

Reputation: 21

releasing memory allocated for char* in C

Can someone, please, explain to me, what is wrong in my code below? As I understand it, I need to release memory allocated for char* - or it will leak it. However, if I use (at the very end of the program free(), I am getting: malloc: * error for object 0x7ff7274027a4: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug Abort trap: 6

without "free()" this code runs just fine and gives me what I need. Thank you in advance!

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

  int main ()
 {
    char *src="start=3.6307436653491267,2.2931731236906048,0";
    char *psrc;
    psrc=calloc((strlen(src)+1),sizeof(char));
    strcpy(psrc,src);
    size_t len= strlen(src);
    len +=1;
    char str[len];
    int count=0;
    char *wt=calloc(3,sizeof(char));
    char *ft=calloc(17, sizeof(char));
    char *finalstr=calloc((strlen(wt) + strlen(ft) + 1), sizeof(char));
    while (psrc != NULL && *psrc != '\0' && count <= len)
    {
        if(psrc[0] == '=')
        {
            psrc +=1;
            strcpy(str, psrc);
            wt=strtok(str, ".");
            ft=strtok(NULL, ".");
            ft=strtok(ft, ",");
            strcpy(finalstr, wt);
            strcat(finalstr, ".");
            strncat(finalstr, ft, 2);
        }
        ++psrc;
        ++count;
   }
   printf("finalstr: %s\n", finalstr);
   //free(psrc);
   exit(EXIT_SUCCESS);
}

Upvotes: 1

Views: 403

Answers (2)

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53006

The error is because you can only pass to free() a pointer that was returned by malloc()/calloc()/realloc() and you are passing the incremented psrc.

For example,

char *string = malloc(SIZE);
free(string + 1);

is undefined behavior, the only acceptable and correct way to call free() would be

free(string);

and you have

psrc += 1;

which changes the value of psrc and it no longer points to the address originally returned by calloc().

Although if you are worried about a memory leak you need to understand them.

In your code, you have

char *wt = calloc(3, sizeof(char));

and then,

wt = strtok(str, ".");

That's exactly a memory leak: Because you now can't free() the memory earlier returned by calloc().

You need to study pointers before you continue, it doesn't make a lot of sense to worry about memory leaks when you have a explicit memory leak in your code and yet you don't know.

I also think that you should reconsider the following statement

without "free()" this code runs just fine and gives me what I need.

The code will not always give you what You need, because it has severe bugs that will cause undefined behavior, so it's IMPOSSIBLE to predict the result anyway.

If you carefully read documentation for the functions used in the below example, you would right the following code

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

int main(void)
{
    const char *src = "start=3.6307436653491267,2.2931731236906048,0";
    const char *equal;
    char *endptr;
    float value;
    int length;
    char *result;

    // Find the equal sign, if not found the function
    // returns and no output is shown
    equal = strchr(src, '=');
    if (equal == NULL)
        return -1;
    // Convert the string to a `float' starting
    // at the `=' sign and up to the `,'
    value = strtof(equal + 1, &endptr);
    // If the first non numeric character wasn't a `,'
    // then this input string is not as we expected it to
    // be so we abort the program.
    if (*endptr != ',')
        return -1;
    // Create a string from the number, with just 2
    // decimal places.

    // Compute the length of the resulting string
    length = snprintf(NULL, 0, "%.2f", value);
    if (length == -1)
        return -1;
    // Allocate space for it
    result = malloc(length + 1);
    if (result == NULL)
        return -1;
    // Finally "print" the number into the string
    snprintf(result, length, "%.2f", value);
    // Now we have the string we wanted
    fprintf(stdout, "%s\n", result);
    // After we've done our work with `result' then we
    // have to `free()' it
    free(result);
    return 0;
}

Upvotes: 2

JMichelB
JMichelB

Reputation: 475

psrcis no longer pointing to its original address. You might want to add psrc -= count; just before freeing the memory.

Upvotes: 0

Related Questions