carraysmemorydirent.h

C unable to read from array of strings out of function


I wrote a function that scans a directory and copies all file names in it to a char** that I pass as a parameter, I'm using dirent.h to get the files in the directory, here is my main & the function:

int main(void)
{
    char** files = 0;
    int size = 0, i = 0;

    size = scanDir(files, "C:\\Users\\user\\test");

    for (i = 0; i < size; i++)
    {
        puts(files[i]);
        free(files[i]);
    }

    free(files);

    getchar();  
    return 0;
}

int scanDir(char** files, char* path)
{
    int size = 0, i = 0;
    DIR* dp = 0;
    struct dirent* ep = 0;

    files = (char**)malloc(sizeof(char*) * size);
    dp = opendir(path);

    if (dp != NULL)
    {
        while (ep = readdir(dp))
        {
            files = realloc(files, sizeof(char*) * ++size);
            files[i] = (char*)malloc(sizeof(char) * (strlen(ep->d_name) + 1));
            strcpy(files[i], ep->d_name);
            i++;
        }
        (void)closedir(dp);
    }

    return size;
}

I'm using visual studio and during debugging files[i] within scanDir does contain the correct filename in each iteration of the while loop but in the for loop, it crashes and in the variable watch it says the it is "unable to read memory" under files

Why is that happening?


Solution

  • files is passed by value, and so when scanDir assigns to it and returns, the change doesn't propagate back to the caller.

    I am afraid you need another level of indirection (char***).

    int main(void)
    {
        char** files = 0;
        size = scanDir(&files, "C:\\Users\\user\\test");
        ...
    }
    
    int scanDir(char*** files, char* path)
    {
        ...
        *files = (char**)malloc(sizeof(char*) * size);
        ...
    }
    

    Alternatively, you could change the scanDir signature to return the newly allocated char** pointer along with the size.