c - 使用 strcpy 和 strcat 时堆栈粉碎

标签 c char strcpy strcat

我已经尝试调试了一段时间,仍然无法弄清楚为什么这会导致堆栈粉碎错误(我认为错误代码是 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;
 }

map 函数与例子。

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:编辑代码以反射(reflect)我所做的更改。

EDIT2:我认为是根据 MCVE 标准完成的?如果我没记错的话应该会跑。

最佳答案

第一个问题:变化

    char copyDirectory[strlen(dir)+1];

    char copyDirectory[strlen(dir)+2];

第二个问题:改变

       char filePath[filePathLength];

       char filePath[filePathLength+1];

第三个问题(初读时似乎没有变化):

     //strcpy(copyDirectory, dir);
     strcat(copyDirectory, dir);

注释掉的代码是正确的:

    strcpy(copyDirectory, dir);

您忘记了尾随空字符的空格。

第四个问题:你忘记处理 opendir 失败了。

第五个问题:这段代码是错误的:

        memset(filePath, 0, filePathLength); //allocat ememory for file path
        strcpy(filePath, strcat(dir, fileName));

更改为:

         strcpy(filePath, copyDirectory);
         strcat(filePath, fileName);

不要在此处写入您的输入变量。这是一个非常糟糕的主意。

在撤消 copyDirectory 的(泄漏的)strdup 并将您非常创新的本地缓冲区放回之后,我能够让代码运行到完成。

关于c - 使用 strcpy 和 strcat 时堆栈粉碎,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39432110/

相关文章:

c - C语言中如何区分以下两种情况

c++ - 如何用单向链表实现一个队列,使其 ENQUEUE 和 DEQUEUE 的时间复杂度为 O(1)?

c++ - 编译器错误 - 没有想法

c - 使用 strtok 标记数字列表的程序中的错误 0Xc0000005

c++ - 指向未指定大小 "(*p)[]"的数组的指针在 C++ 中非法但在 C 中合法

c - 我是否需要包含我包含的文件所依赖的文件?

c - 使用 C 返回数组

c# - 用等效字符串表示 Char

将 char* 转换为 unsigned char*

c - strcpy where src == dest 是否严格定义?