简体   繁体   中英

segmentation fault return a string array from a function

I have created a function that creates a dynamic string array with dynamic string length and then I return it to my main function. Everything works fine inside my function but when I try to print the array in main I get a segmentation fault after the 4th string - first two string don't print out correct either. This part of the program is supposed to find out all entries in a directory and its sub-directories and store them in main memory.

Here's the result:

Path[0]=A/New Folder. - i=0
Path[1]=A/atext - i=1
Path[2]=A/a - i=2
Path[3]=A/alink - i=3
Path[4]=A/afolder - i=4
Path[5]=A/afolder/set008.pdf - i=0
Path[6]=A/afolder/anotherfolder - i=1
Path[7]=A/afolder/anotherfolder/folderOfAnotherFolder - i=0
Path[8]=A/afolder/anotherfolder/folderOfAnotherFolder/mytext - i=0
Path[9]=A/afolder/anotherfolder/mytext - i=1
Path[10]=A/afolder/set001.pdf - i=2
Entries in directory: A
��
��
A/a
A/alink
Segmentation fault

And here's the code: function:

char ** getDirContents(char *dirName,char **paths ) 
{   
    DIR * tmpDir;
    struct dirent * entry;
    //char  tmpName[512];
    char * tmpName=NULL;
    struct stat node;
    int size=0;
    int i=0;
    //paths=NULL;

    if((tmpDir=opendir(dirName))==NULL){
        perror("getDirContents opendir"); 
        return NULL;
    }
    i=0;
    while ((entry=readdir(tmpDir))!=NULL) 
    {
        //if (entry->d_ino==0) continue;
        if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)//Ignore root & parent directories
            continue;but I

        tmpName =(char *)malloc(strlen(dirName)+strlen(entry->d_name)+2);
        strcpy(tmpName,dirName);
        strcat(tmpName,"/");
        strcat(tmpName,entry->d_name);
        //printf("\ntmpName[%d]:%s",count,tmpName);

        paths=(char**)realloc(paths,sizeof(char*)*(count+1));
        paths[count]=NULL;
        //paths[count]=(char*)realloc(paths[count],strlen(tmpName)+1);
        paths[count]=(char*)malloc(strlen(tmpName)+1);

        //memcpy(paths[count],tmpName,strlen(tmpName)+1);
        strcpy(paths[count],tmpName);
        printf("\nPath[%d]=%s - i=%d",count,paths[count],i);

        count++;

        if(lstat(tmpName,&node)<0)    
            { 
                printf("\ntmpName:%s",tmpName);
                perror("getDirContents Stat");
                exit(0);
            }
        if (S_ISDIR(node.st_mode))
            {
                getDirContents(tmpName,paths);//Subfolder
            }

        //printf("\n%s,iters:%d",tmpName,i);
        free(tmpName);
        tmpName=NULL;
        i++;
    }
close(tmpDir);
return(paths);
}

main:

char **A=NULL;
count=0;
A=getDirContents(dir1,NULL);
Aentries=count;
count=0;
//B=getDirContents(dir2,NULL);
printf("\nEntries in directory: %s",dir1);
for(i=0;i<Aentries;i++)
{
     printf("\n%s",A[i]);
}

count is a global variable

I just can't figure out what is wrong I think I use the return command properly. I also tried the same code with paths as a global variable and it worked fine (main printed out the correct results). I have a feeling it has something to do with the recursive call of my function

Your problem is that, as per the standard, your realloc call may (and probably will) return a pointer to a different memory location than the original .

It's a tricky one, and it's a little hard to explain and visualize, but I'll do my best.

When you call your function originally, it creates a new stack frame (let's call it A ). It allocates paths to an address (say 0x01 ), do some stuff with it, then the function calls itself recursively with the paths address as an argument.

When you call your function recursively, it creates a new stack frame (let's call it B ), in which you realloc the paths pointer - which changes its address from 0x01 to 0x02 - do some stuff with it, and then return it.

But when B returns, the paths pointer in A still point to the old location, 0x01 , even though it's not valid anymore and has been moved to 0x02 .

The solution is simple, make sure that you point paths to the new location when the recursive call ends . So instead of:

getDirContents(tmpName,paths); //Subfolder

...you'd do:

paths = getDirContents(tmpName,paths); //Subfolder

Also, make sure you check the return value of realloc and malloc (against NULL ), and don't cast the return value of malloc .

Your code has an Undefined Behavior .

You call the function as:

A=getDirContents(dir1,NULL);

and the function is defined as:

char ** getDirContents(char *dirName,char **paths ) 

Further you call realloc on paths .

paths=(char**)realloc(paths,sizeof(char*)*(count+1));

This causes Undefined Behavior.

The standard mandates that the pointer being passed to realloc should exactly match the pointer which was allocated dynamic memory using a memory management function. Memory management functions specified by the standard are: aligned_alloc , calloc , malloc , and realloc .

The pointer( paths ) you are passing to realloc() was not returned by any of these and hence the Undefined Behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM