2012-03-11 2 views
0

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

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

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

главная:

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

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

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

+3

Пожалуйста, сварить это до * простенького * теста (не более 10-15 строк). См. Http://sscce.org. –

+1

Ну нашел. Это действительно был вызвательный вызов моей функции Я изменил это: getDirContents (tmpName, paths); // Подпапка к этому: paths = getDirContents (tmpName, paths); // Подпапка теперь работает нормально –

+0

что такое 'count ', глобальный? – phoxis

ответ

1

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

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

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(), не был возвращен ни одним из них и, следовательно, неопределенным поведением.

+0

Я не понимаю, почему он не определен, я изменил это getDirContents (tmpName, paths); // Подпапка к paths = getDirContents (tmpName, paths); // Подпапка - это все еще неопределенное поведение? Является ли параметр NULL в вызове основной проблемой? В чем проблема вызова realloc на дорогах? –

+0

О, я думаю, что понял, что вы имели в виду –

+2

Подождите, что? Вызов 'realloc' с указателем' NULL' - это корректное поведение: C11, 7.22.3.5/3, * «Если' ptr' - нулевой указатель, функция 'realloc' ведет себя как функция' malloc' для указанный размер. * * – netcoder

1

Ваша проблема заключается в том, что в соответствии со стандартом, ваш вызов 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) и don't cast the return value of malloc.

Смежные вопросы