Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a string from a function in C

Tags:

c

string

pointers

I have a c function that I want to return a string.

If I print the string before it is returned then I see croc_data_0186.idx

If I try and print the string that is returned then I see croc_data_á☼

Can anyone see what I am doing wrong?

Problem function:

char* getSegmentFileName(FILE *file, int lineLength, int lineNumber)
{
    char* fileNameString;

    fseek(file, lineNumber * lineLength, SEEK_SET);

    char line[lineLength];
    fgets(line, lineLength, file);

    char *lineElements[3];
    lineElements[0] = strtok(line, ":");
    lineElements[1] = strtok(NULL, ":");
    lineElements[2] = strtok(NULL, ":");

    fileNameString = lineElements[2];

    printf ("getSegmentFileName fileNameString is: %s \r\n", fileNameString);

    return fileNameString;
}

Calling code:

int indexSearch(FILE *file, char* value, int low, int high, char* segmentFileName)
{
    ...

    segmentFileName = getSegmentFileName(file, lineLength, mid);
    printf ("indexSearch: segmentFilename3 is: %s \r\n", segmentFileName);

    ...
}
like image 936
Dunc Avatar asked Feb 21 '12 14:02

Dunc


2 Answers

You are returning a pointer to local data, which is not valid after the function returns. You have to allocate the string properly.

This can be done in either the calling function, by supplying a buffer to the called function, and it copies the string over to the supplied buffer. Like this:

char segmentFileName[SOME_SIZE];
getSegmentFileName(file, lineLength, mid, segmentFileName);

and the getSegmentFileName function:

void getSegmentFileName(FILE *file, int lineLength, int lineNumber, char *segmentFileName)
{
    /* ... */

    strcpy(segmentFileName, fileNameString);
}

The other solution is to allocate the memory for the string in getSegmentFileName:

return strdup(fileNameString);

but then you have to remember to free the string later.

like image 199
Some programmer dude Avatar answered Oct 02 '22 16:10

Some programmer dude


This is because you are returning a pointer to local. This is undefined behavior.

strtok returns a pointer into the line character array. You put that pointer into fileNameString, and return to the caller. At this time the memory inside line becomes invalid: any garbage can be written into it.

To avoid this problem, you should either pass a buffer/length pair for the return value, or use strdup() on the string that you are returning. In the later case you should remember to free the memory allocated for the returned string by strdup().

On a related subject, you should avoid using strtok, because it is not re-entrant, and will cause issues in multithreaded environments. Consider using strtok_r instead.

like image 43
Sergey Kalinichenko Avatar answered Oct 02 '22 16:10

Sergey Kalinichenko