【发布时间】:2017-01-18 19:36:09
【问题描述】:
我已经尝试调试了一段时间,仍然无法弄清楚为什么这会导致堆栈粉碎错误(我认为错误代码是 6,或者中止。本质上这个函数需要一个目录,打开一个文件然后将该文件放入一个函数中以便它可以使用该文件,然后输出它通过该函数的次数。
int map(char* dir, void* results, size_t size, int (*act)(FILE* f, void* res, char* fn))
{
printf("%s\n", dir);
char copyDirectory[strlen(dir)+1];
//adds the slash
strcpy(copyDirectory, dir);
strcat(copyDirectory, "/");
//before the psuedocode, get all the files in the directory
int numFiles = nfiles(copyDirectory);
DIR* directory = opendir(copyDirectory);
//if there aren't any files, then we exit
if(numFiles == 0)
{
closedir(directory);
return -1;
}
//reads the file from the directory
struct dirent* readFile = readdir(directory);
int output = 0;
while(readFile!=NULL)
{
if(readFile->d_type==DT_REG)
{
//step 2: obtain filepath
char* fileName = readFile->d_name;
int filePathLength = strlen(dir) + strlen(fileName) + 1;//add one for the slash
char filePath[filePathLength];
memset(filePath, 0, filePathLength); //allocat ememory for file path
strcpy(filePath, strcat(dir, fileName));
//step 3: open file
FILE* file = fopen(filePath, "r");
//if the file is unreachable, exit
if(file==NULL)
{
closedir(directory);
return -1;
}
//step 4: perform some action and store result
strcpy(dir, copyDirectory);
act(file, results, fileName);
//step 5: close file
fclose(file);
//to go through loop: increment the readFile
++output;
}
readFile = readdir(directory);
}
closedir(directory);
return output;
}
映射函数与示例。
int map(char* dir, void* results, size_t size, int (*act)(FILE* f, void* res, char* fn))
{
char* copyDirectory = strdup(dir);
DIR* directory = opendir(dir);
int output = 0;
struct dirent* readFile = readdir(directory);
while(readFile!=NULL)
{
if(readFile->d_type==DT_REG)
{
//step 2: obtain filepath
char* fileName = readFile->d_name;
int filePathLength = strlen(dir) + strlen(fileName) +2;//add one for the slash
char filePath[filePathLength+1];
memset(filePath, 0, filePathLength); //allocat ememory for file path
strcpy(filePath, strcat(dir, fileName));
//step 3: open file
FILE* file = fopen(filePath, "r");
//if the file is unreachable, exit
if(file==NULL)
{
closedir(directory);
return -1;
}
//step 4: perform some action and store result
strcpy(dir, copyDirectory);
act(file, results, fileName);
//step 5: close file
fclose(file);
//to go through loop: increment the readFile
++output;
}
readFile = readdir(directory);
}
closedir(directory);
return output;
}
//Sample Map function action: Print file contents to stdout and returns the number bytes in the file.
int cat(FILE* f, void* res, char* filename) {
char c;
int n = 0;
printf("%s\n", filename);
while((c = fgetc(f)) != EOF) {
printf("%c", c);
n++;
}
printf("\n");
return n;
}
int main(int argc, char const *argv[])
{
char directory[]= "../rsrc/ana_light/";
size_t size = 100;
void* results[500];
int mapCat = map(directory, results, size, cat);
printf("The value of map is %d.\n", mapCat);
return EXIT_SUCCESS;
}
失败的地方是在它执行并打印到输出之后。该功能应打印出您拥有的文件的内容。目录列表的末尾需要有一个“/”。目前它打印文件内容并以它读取的文件数量的值退出,但在退出堆栈粉碎错误后它会丢失。
EDIT1:编辑代码以反映我所做的更改。
EDIT2:我认为是按照 MCVE 标准完成的?如果我没记错的话应该跑。
【问题讨论】:
-
在
char copyDirectory[strlen(dir)+1]; strcpy(copyDirectory, dir);strcpy()使用每个分配的字节,但是你在strcat(copyDirectory, "/");写超出了数组的末尾。这会破坏堆栈。 -
嗯,甚至在这发生之前,它就已经在破坏堆栈了。即使我将“/”硬编码到 main 方法中,它也会产生错误。
-
请查看如何创建 MCVE (minimal reproducible example),然后添加(最少的)必要代码,以便我们可以执行您展示的内容。您应该将其添加为您的代码的新版本 - 保持原始可见,因为您有一个解决原始代码中实际问题的答案。您在哪个平台上使用哪个编译器?您是否使用
valgrind来帮助诊断问题?您可以...吗? (并非在所有平台上都可用。) -
给你一个严肃的问题:如果你省略了
act参数和对函数的调用,你还会遇到崩溃吗?如果是这样,请忽略它;它将大大简化您的 MCVE。 -
抱歉,没听说过 MCVE 标准。修复了代码以解决此问题。它需要与行为部分配合使用。它确实可以使用它,但最后它会以检测到堆栈粉碎错误而终止。