5

I am working on some kind of file sharing program which is written in C. There is a function that can read a data file and store the data into a string and return this string to main function and the main function send back to client. Codes are shown below

char* ListFiles(){
    FILE *fp;
    char file[30];
    char *f;
    if((fp=fopen("list","r"))==NULL)  
    {
        ...
    }
    while (!feof(fp))
    {
        fgets(file,50,fp);
    }
    fclose(fp);
    f=file;
    printf("%s",f); //get display!!!
    return f;
}
int main(){
      char *files;
      ...
      ...
      files=ListFiles();
      printf("%s",files); //nothing display!!
      sent();
}

However, this method doesn't work. There is nothing display and of course nothing is sent. But I do get the correct display in function ListFiles(). I don't know what happen. I also use strcpy() and it still fail to work.

Mat
  • 202,337
  • 40
  • 393
  • 406
panda
  • 1,344
  • 3
  • 14
  • 35
  • 1
    `char file[30]; char *f; f = file;` nothing good happens here. Think a second about it and write it properly. – Griwes Apr 12 '12 at 20:43
  • 2
    This is unrelated, but your `file` variable can only hold 30 characters and you're reading more than that. `file` will overflow. – rid Apr 12 '12 at 20:47
  • 1
    In addition, the `fgets` will be called repeatedly with the same buffer until the file reaches its end, so that after the loop the buffer will contain only the last part of the file. – Mr Lister Apr 12 '12 at 20:51
  • Here a good example on how to do different things with strings and pointers in C https://stackoverflow.com/a/46344713/5842403 – Joniale Sep 22 '17 at 08:55

6 Answers6

10

Follow George Skoptsov recommendations. But If you don't have the strdup() function,then use this:

char* strdup(const char* org)
{
    if(org == NULL) return NULL;

    char* newstr = malloc(strlen(org)+1);
    char* p;

    if(newstr == NULL) return NULL;

    p = newstr;

    while(*org) *p++ = *org++; /* copy the string. */
    return newstr;
}

And then:

#include <string.h> /* strlen() call */
#include <stdlib.h> /* NULL, malloc() and free() call */

/* do something... */

char* ListFiles() {
        /* .... */ 
         return strdup(f);
}

Or instead of char file[30]; do a dynamic memory allocation: char* file = malloc(30); then you can do return f; and it will work fine because f now is not a pointer to a local variable.

Community
  • 1
  • 1
Jack
  • 16,276
  • 55
  • 159
  • 284
  • Even if you don't have `strdup`, you always have `strcpy` when including ``... – Mr Lister Apr 13 '12 at 08:56
  • 1
    Here a good example on how to do different things with strings and pointers in C https://stackoverflow.com/a/46344713/5842403 – Joniale Sep 22 '17 at 08:55
9

What you're doing is returning a pointer to a local variable, which used to be allocated on stack.

Change your return statement to

return strdup(file);
George Skoptsov
  • 3,831
  • 1
  • 26
  • 44
4

file is a stack variable in ListFiles() and you're returning a pointer to it. Once you return from that function, the variable will cease to exist, so the returned pointer will be invalid.

If you want to return a string, you should allocate it on the heap, return it, use it, then free it once you're done using it.

rid
  • 61,078
  • 31
  • 152
  • 193
2

You are returning a pointer points to the stack variable. When the function returns, the stack gets popped off. The stack variable no longer exists, the pointer become a dangling pointer.

One solution is to allocate the appropriate amount of memory in the main function, and pass the pointer to the memory to the helper function.

Quincy
  • 1,923
  • 5
  • 27
  • 37
0

you shouldn't return data that sits on automatic storage, when you return it goes out of scope.

pizza
  • 7,296
  • 1
  • 25
  • 22
0

You're trying to display a string value char file[30] that is allocated on the stack (function stack). The content of this memory is not guaranteed after the method return. You should allocate it dynamically (for ex. malloc) or eventually use global value, or allocate it on the stack of the outer function (in your example main() function)

Eric
  • 1,685
  • 1
  • 17
  • 32