ошибка сегментации возвращает массив строк из функции - PullRequest
0 голосов
/ 11 марта 2012

Я создал функцию, которая создает динамический массив строк с динамической длиной строки, а затем возвращаю его в свою основную функцию. Внутри моей функции все работает нормально, но когда я пытаюсь распечатать массив в основном, я получаю ошибку сегментации после 4-й строки - первые две строки также не выводятся правильно. Предполагается, что эта часть программы обнаружит все записи в каталоге и его подкаталогах и сохранит их в основной памяти.

Вот результат:

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

А вот код: Функция:

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);
}

главный:

* * 1010

count является глобальной переменной

Я просто не могу понять, что не так, я думаю, что правильно использую команду возврата. Я также попробовал тот же код с путями, что и глобальная переменная, и он работал нормально (основной выводил правильные результаты). У меня такое ощущение, что это как-то связано с рекурсивным вызовом моей функции

Ответы [ 2 ]

1 голос
/ 15 января 2013

Ваша проблема в том, что, в соответствии со стандартом, ваш вызов realloc может (и, вероятно, будет) возвращать указатель на место в памяти, отличное от исходного .

Это сложно, и это немного сложно объяснить и визуализировать, но я сделаю все возможное.

Когда вы вызываете свою функцию изначально, она создает новый фрейм стека (назовем его A). Он выделяет paths адресу (скажем, 0x01), делает с ним что-то еще, затем функция вызывает себя рекурсивно с адресом paths в качестве аргумента.

Когда вы вызываете свою функцию рекурсивно, она создает новый кадр стека (назовем его B), в котором вы realloc указатель paths - который меняет свой адрес с 0x01 на 0x02 - сделайте что-нибудь с этим, а затем верните.

Но когда возвращается B, указатель paths в A все еще указывает на старое местоположение, 0x01, даже если оно больше не действует и было перемещено в 0x02.

Решение простое, убедитесь, что вы указали paths на новое местоположение, когда рекурсивный вызов завершится . Так что вместо:

getDirContents(tmpName,paths); //Subfolder

... вы бы сделали:

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

Кроме того, убедитесь, что вы проверили возвращаемое значение realloc и malloc (против NULL), и не приведите возвращаемое значение malloc.

1 голос
/ 11 марта 2012

Ваш код имеет неопределенное поведение .

Вы вызываете функцию как:

A=getDirContents(dir1,NULL);

, а функция определяется как:

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

Далее вы вызываете realloc на paths.

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

Это вызывает неопределенное поведение.

Стандарт предписывает, чтобы указатель, передаваемый в realloc, точно совпадал с указателем, который был выделен динамической памяти с использованием функции управления памятью.Стандартные функции управления памятью: aligned_alloc, calloc, malloc и realloc.

Указатель (paths), который вы передаете на realloc(), не был возвращенлюбой из них и, следовательно, неопределенное поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...