【问题标题】:C Programming - Segmentation fault when Manipulating Array of StringsC 编程 - 操作字符串数组时出现分段错误
【发布时间】:2015-05-20 13:46:50
【问题描述】:

我正在努力解决当 dns 变量从大小 10 更改为大小 32 时发生的分段错误。我相信 main 中 dns ariable 的声明正在创建一个由 10 个字符串组成的数组,然后当增加到 32 个时,一个由 32 个字符串组成的数组。

因此,当使用大小为 10 的 dns 变量执行时,我得到了以字母 D 开头的 4 个目录名称的输出。这是预期的输出。

如果我将 dns 变量的大小增加到 32,我仍然会得到 4 个目录名称,然后立即出现分段错误。

自从我编码以来已经很长时间了,我确信我在某个地方违反了记忆。

非常感谢任何帮助。

谢谢,

丹。

void ld_dirs(char *strings[])
{
   int count;
   DIR *dp;
   struct dirent *ep;

   dp = opendir ("/tmp/sysinfo/inputs");
   if (dp != NULL)
   {
      count = 0;

      while (ep = readdir (dp))
      {
         if (ep->d_name[0] == 'D')
         {
            strings[count] = malloc (80 * sizeof(char));
            strings[count] = ep->d_name;
            count ++;
         }
      }

      closedir (dp);
   }
   else
      perror ("Could not open the directory");
}

int main ()
{
   char cwd[120];
   int count, count2;
   char *dns[10];
   char *path;
   if (getcwd(cwd, sizeof(cwd)) != NULL)
      printf ("\nCurrent working directory : %s\n\n\n", cwd);
   else
      perror ("getcwd() error");

   ld_dirs (dns);

   count = 0;

   puts ("List of valid inputs :\n");

   while (dns[count] != NULL)
   {
      puts (dns[count]);
      count ++;
   }     

   printf ("There are %d valid inputs\n", count);
   return 0;
}

【问题讨论】:

  • 发布这个问题是一场噩梦,我不断遇到格式错误的代码问题。使用 char *dns[10] 执行的输出; is : \n当前工作目录 : /data/test \n 有效输入列表 : \n DTest1.vga \n DTest234.video \n DTest123.vga \n DTest800.video .... 当声明更改为 char * dns[32];输出是相同的,但是在最后一行之后,出现“分段错误”。 .....对不起,经过多次编辑,我意识到这条评论在格式或可读性方面并没有好多少。丹。
  • 您是否阅读了有关如何格式化的 stackoverflow.com 在线帮助?

标签: c arrays string


【解决方案1】:

我看到的问题:

  1. 数组的大小。

    您已声明:

    char *dns[10];
    

    您在ld_dirs 中没有任何代码,以确保您不会使用strings 超出其合法持有的范围。

  2. 您尚未将 dirs 中的项目初始化为 NULL,但您指望在以下 while 循环中将项目的值设为 NULL

    while (dns[count] != NULL)
    {
       puts (dns[count]);
       count ++;
    }     
    

您可以通过以下方式解决这些问题:

  1. dns中的项目初始化为NULL

    char *dns[10] = {0};
    
  2. 将数组的大小传递给ld_dir,并确保您不会使用超出法律规定的任何内容。

    函数界面改为:

    void ld_dirs(char *strings[], int size)
    

    将调用改为:

    ld_dirs (dns, sizeof(dns)/sizeof(*dns));
    

【讨论】:

    【解决方案2】:

    我马上看到的一个问题是您继续将readdir 的返回值用于不同的字符串表条目,并覆盖您刚刚分配用于保存名称的地址。但我不认为 readdir 保证为每次调用返回一个新的、分配的目录条目结构。我怀疑不会,访问之前的其中一个导致分段错误只是时间问题。

    您需要从使用readdir 读取的每个目录条目中复制数据:

      while (ep = readdir (dp))
      {
         if (ep->d_name[0] == 'D')
         {
            strings[count] = malloc(80 * sizeof(char));
            //ERROR: strings[count] = ep->d_name;
            strcpy(strings[count], ep->d_name);  //CORRECTED
            count ++;
         }
      }
    

    我没有检查超出这一点的其他错误。

    【讨论】:

    • 感谢您的回复!我实施了更改,但是仍然看到分段错误。 strcpy 是一个更好的实现,所以一定要保留它。再次感谢!
    • @DanG 感谢您的反馈。我没有检查超出我上面提到的点的代码,因为其他答案似乎涵盖了其他问题。
    猜你喜欢
    • 2019-08-21
    • 1970-01-01
    • 2022-11-18
    • 1970-01-01
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多