gpt4 book ai didi

c - Realloc 在目录/文件名的递归存储期间咀嚼字符串数组

转载 作者:行者123 更新时间:2023-11-30 15:28:49 26 4
gpt4 key购买 nike

我在 C 程序(cygwin 上的 GNU)中使用 opendir/readdir 将一些嵌套目录中的文件名收集到字符串数组中(该程序主要使用 C89 和早期约定)。由于我事先不知道文件的数量,所以我决定使用malloc/realloc来执行动态内存分配。通过递归调用传递指针数组来收集文件名。问题在于,早期调用 getlist() 期间存储的文件名在后续存储步骤中被损坏。进入子目录,对 realloc 执行第二次调用并从子目录中退出后,执行 realloc 后存储边缘的字符串逐渐损坏因为附加文件名被收集在父目录中。

如果我使用单个malloc分配来分配内存来创建一个大的初始指针数组,我可以避免这个问题,但我希望能够使用realloc 。任何人都可以指出我做错了什么,特别是我猜这就是我在这种情况下使用 realloc 的方式?

#include <string.h>
#include <stdlib.h>
#include <signal.h>

#include <stdio.h>
#include <stddef.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>

// function prototypes
char ** getlist(char ** filelist,long int *numfiles,char *dirname);

extern int stat (const char *filename, struct stat *buf);
extern DIR * opendir (const char *_dirname);
extern struct dirent * readdir (DIR *dirstream);

int main(int narg, char* argv[])
{

// vars
char * dirname;
char **filelist, **traverse;
long int numfiles =0;
FILE* pfile;

//....................................
// and go ...

if ( (filelist = (char **)malloc(sizeof(char *))) == NULL )
{
printf("Fatal malloc error!\n");
exit(3);
}
filelist = getlist(filelist,&numfiles,argv[1]); // argv[1] is dir name

// list the stored filenames and write to file

pfile = fopen("listoutput.txt","w");
printf("Stored filenames (N=%i):\n",numfiles);
traverse = filelist;
while(*traverse)
{
printf("%s\n",*traverse);
fprintf(pfile,"%s\n",*traverse);
traverse++;
}
fclose(pfile);

// free etc should go here...

return 0 ;
}

//-------------------------------------------------------------------------------

char ** getlist(char** filelist, long int *numfiles, char* dirname)
{

// variables
char filename[200];
char dirname_[200];
DIR * directory;
struct dirent * file;

strcpy(dirname_,dirname);

// for checking file type
// macro: int S_ISREG (mode_t m)
struct stat* filestat = malloc(sizeof(struct stat));
int sizeofchar = sizeof(char); // fields: mode_t st_mode, unsigned char d_namlen

char **traverse, **ptemp;

//aux
long int ii, icheck;

// check number of valid files in dirname and allocate memory in char pointer array
ii=0;
directory = opendir (dirname_);
while(file = readdir(directory))
{
sprintf(filename,"%s/%s",_dirname_,file->d_name);
icheck = stat(filename,filestat);
if (icheck==0)
{
if (S_ISREG(filestat->st_mode)) ii++;
}
else
{
printf("Couldn't check file type of file \"%s\" (icheck = %i)\n", filename, icheck);
}
}

// generate enough room for all the filename strings

if ( (filelist=(char **)realloc(filelist,sizeof(char *)*(*numfiles+ii+1))) == NULL )
{
printf("Fatal realloc error!\n");
exit(3);
}

traverse = filelist + *numfiles;

// now store the filenames in filelist ...

(void) rewinddir (directory);
while(file = readdir(directory))
{
sprintf(filename,"%s/%s",dirname_,file->d_name);
icheck = stat(filename,filestat);
if (icheck==0 && S_ISREG(filestat->st_mode))
{
*traverse = (char *)malloc(sizeofchar*(strlen(filename)+1));
strcpy(*traverse,filename);
traverse++;
(*numfiles)++;

// spit out what we have so far
printf("\nCurrent list (looping):\n-----------\n");
ptemp = filelist;
ii=*numfiles;
while(ii--)
{
printf("%s\n",*ptemp);
ptemp++;
}
printf("\n-----------\n");

//sleep(1);
}
else if (icheck==0 && S_ISDIR(filestat->st_mode))
{
if (strcmp(file->d_name,".")!=0 && strcmp(file->d_name,"..")!=0 )
{
printf("Processing folder %s\n", filename);
filelist = getlist(filelist,numfiles,filename);
traverse = filelist + *numfiles;

// spit out what we have so far
printf("\nCurrent list (returned from getlist):\n-----------\n");
ptemp = filelist;
while(*ptemp)
{
printf("%s\n",*ptemp);
ptemp++;
}
printf("\n-----------\n");

}
}
}
(void) closedir (directory);

*traverse = NULL;

return filelist;
}

最佳答案

分配的内存不足。

如果没有为终止空字符分配足够的空间,然后执行 strcpy(),内存可能会损坏。

// *traverse = (char *)malloc(sizeofchar*strlen(filename));
// strcpy(*traverse,filename);

size_t size = strlen(filename) + 1; // Add 1!
*traverse = malloc(size);
memecpy(*traverse, filename, size);

次要:无需转换 malloc() 的返回值。一旦代码知道了大小,就可以使用 memcpy()strcpy()

--

更新

不要打印 ii 次,而是打印直到 *temp == NULL

 while (ii--) {
if (*ptemp == NULL) break;
printf("%s\n", *ptemp);
ptemp++;
}

ii 基于目录大小,但文件名的使用不包括“.”和“..”。

可疑代码仍然存在除 GTG 之外的其他问题。

关于c - Realloc 在目录/文件名的递归存储期间咀嚼字符串数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26444768/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com