【问题标题】:Declaration unexpected behavior声明意外行为
【发布时间】:2019-01-25 01:03:33
【问题描述】:

所以我有两个简单的程序。它们非常相似,但是一种代码可以正常工作,而另一种则根本不起作用。这里有人知道为什么吗?

尽管没有初始化 char* 名称,但此代码可以正常工作。

#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

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

   DIR* d;
   struct dirent* dir;
   char* name;
   d=opendir(".");
   if(d){
        while((dir=readdir(d))!=NULL){
             strcpy(name,dir->d_name);
             printf("%s\n",name);
        }
        clode(dir);
   }
  return 0;
}

第二个代码在声明部分有细微差别,这导致变量“name”无法访问。

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

   DIR* d;
   struct dirent* dir;
   char* surname = "Surname";
   char* name;
   d=opendir(".");
   if(d){
        while((dir=readdir(d))!=NULL){
             strcpy(name,dir->d_name);
             printf("%s\n",name);
        }
        clode(dir);
   }
  return 0;
}

运行第二个代码时,我在strcpy(name,dir-&gt;d_name) 之后立即收到“分段错误”,当我尝试在 GDB 调试器下打印变量“名称”时,我收到消息 $1 = 0x1 &lt;error: Cannot access memory under address 0x1&gt;。 为什么这个错误信息没有出现在第一个程序中?声明 char* surname = "Surname"; 会导致这种运行时错误有什么大不了的?

附:我知道在这个例子中我从不使用变量 'surname' 并且我知道在这段代码中不需要strcpy(name,dir-&gt;d_name)。此代码是更大代码的一部分,这是提取导致错误的重要部分的结果(试图生成更小的代码集)。

谢谢。 问候

【问题讨论】:

  • 没有为char* name; 分配内存,所以strcpy(name,dir-&gt;d_name) 将失败。 “尽管char* name 没有初始化,但第一个代码工作没有问题。”这是一个不幸的中断,未定义行为的一个结果是代码显然可以工作。
  • 有用的问题是,“namechar* name; ....strcpy(name,dir-&gt;d_name); 有什么价值。由于指针 name 从未被分配任何东西,strcpy(name,... 正在接收垃圾。

标签: c strcpy fault


【解决方案1】:

char* name; 未初始化...它指向的位置未定义。它可能会起作用。可能不会。

添加char* surname = "Surname" 会稍微改变你的变量,允许 name 指向其他地方。

您真正需要的是 char name[NAME_MAX] 之类的东西来分配可预测的存储空间。

【解决方案2】:

由于 name 未初始化,因此尝试将 strcopy 与它一起使用是未定义的行为。这意味着无论发生什么都是不可预测的错误代码(这并不意味着它失败,只是坏事可能发生并且它应该失败. 一般来说,UB 可能最终还是会解决,这可能就是发生了什么。)

修复此错误的一种方法是:

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

   DIR* d;
   struct dirent* dir;
   char* surname = "Surname";
   char* name = NULL;

   d=opendir(".");
   if(d){
        while((dir=readdir(d))!=NULL){
             name = realloc(name, strlen(d->name)+1); // Needs to be one char longer 
                                                      // to account for the null terminator.
             strcpy(name,dir->d_name);
             printf("%s\n",name);
        }
        free(name);
        clode(dir);
   }
  return 0;
}

【讨论】:

  • malloc(NAME_MAX),而不是 sizeof(char *),它的值为 1。
  • @Gilbert 假设定义了一些最大尺寸(除非你希望它是可能的绝对最大尺寸,但我相信你会说 SIZE_MAX )——这不是必需的大小写,因为名称被重新分配以适应此字符串的大小。
  • 抱歉……我的错……我最近犯了太多愚蠢的编程错误。
  • 没关系,您的解决方案是个好主意,因为重新分配内存并不便宜 - 以这种方式使用 realloc 有点奇怪,但它应该是明确定义的。
猜你喜欢
  • 1970-01-01
  • 2017-07-26
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-03
  • 2017-04-16
相关资源
最近更新 更多