编译器忽略从函数返回本地char *的代码

时间:2011-07-08 18:40:03

标签: c++

据我所知,下面的代码很糟糕。但是,Visual Studio 2010并没有给我任何警告。

char* CEmployee::GetEmployeeName()
{
  char* szEmployeeName = "";
  CEmployeeModel* model = GetSwitchMod();
  if (model != NULL)
  {
    szEmployeeName = model->GetName();
  }

  return szEmployeeName; 
}  

6 个答案:

答案 0 :(得分:4)

调试代码不是编译器的工作。

lint或类似的静态检查程序可能会发现这一点。如果您有一个包含它的高级VS版本,请尝试运行Code Analysis。确保使用/W4构建并修复所有警告错误。

答案 1 :(得分:2)

这里返回szEmployeeName实际上不是错误 - 字符串是静态分配在只读内存中(ELF可执行文件中的.rodata部分)。引用(C ++ 03)标准:

  

<强> 2.13.4.1

     

普通的字符串文字有类型   “n const char数组”和 static   存储持续时间(3.7),其中n是   如下定义的字符串大小,   并使用给定的初始化   字符。

     

<强> 3.7.1

     

所有既没有动态的物体   储存时间也不是当地的   静态存储时间。 存储   因为这些物体应该持久   计划的持续时间

另一方面,尝试修改此字符串会导致未定义的行为 - 在这种特殊情况下,您很可能会在运行时遇到崩溃。 szEmployeeName应该真正声明为const char*(并且有标准允许使用字符串文字初始化普通char *的历史原因)。再次引用标准:

  

<强> 2.13.14.2

     

尝试修改的效果   字符串文字未定义。

答案 2 :(得分:2)

您没有返回对局部变量的引用,因为您按值返回,因此复制了局部变量 - 指针。

不要将指针与其指针混淆。

如果有的话,你将返回一个悬空指针(虽然实际上字符串文字缓冲区可能在某处的静态内存中)。悬空指针在编译时不会被诊断出来。

如果 model->GetName()返回动态分配的缓冲区,使指针不再指向字符串文字,那么您的代码就可以了。

TRWTF是你没有写char const* szEmployeeName = ""。退出const已经被弃用了十多年,并且在C ++ 0x中是非法的。令人担忧的是,很多人仍在这样做。

更糟糕的是,仍有人使用char*代替字符串,而不是std::string

答案 3 :(得分:0)

你最后会返回指向char的指针。当代码离开函数*时,你确定指针所指的内存仍处于活动状态*(model->GetName()返回的生命周期是什么)

*编辑:“循环”错误。

答案 4 :(得分:0)

在所有情况下,此代码不一定是“错误的”。如果从GetName返回的指针所指向的东西仍然存在,并且从GetEmployeeName返回的指针未被写入,那么代码似乎是格式正确的。无法合理地期望编译器对您的所有代码进行全面分析,以告诉您指针操作是否存在实际问题。

你应该使用std::string作为@Tomalak Geret'kal在他的回答中指出。然后解决所有这些终身问题。

有一点你可以说“为什么我这样写代码?”并且编译器不会花费太多的时间来警告你程序中每个可能的未定义行为(由于某种原因它未定义)。

答案 5 :(得分:0)

这段代码很好。这里没有任何东西可能导致释放szEmployeeName的目标。

如果modelNULL,则返回指向""的指针。使用非const指针肯定是有问题的,但字符串文字""在程序的生命周期中存活,返回它并不是错误。

如果model为非null,则返回model->GetName()返回的指针。由于CEmployee::GetEmployeeName()没有释放任何内存,因此返回的指针与从model->GetName()获取指针时的指针一样有效。具体来说,指针有效,或者是悬空指针,表示CEmployeeModel->GetName()中的错误。

CEmployeeModel::GetName()没有正确但CEmployee::GetEmployeeName返回错误指针的情况。