【问题标题】:C/C++ Char Pointer CrashC/C++ 字符指针崩溃
【发布时间】:2011-05-12 17:27:16
【问题描述】:

假设一个返回固定“随机文本”字符串的函数写成这样

char *Function1()
{ 
return “Some text”;
}

如果程序不小心试图改变doing的值,那么程序可能会崩溃

Function1()[1]=’a’;

函数调用之后的方括号是什么,试图这样做会导致程序崩溃?如果您熟悉这一点,任何解释将不胜感激!

【问题讨论】:

  • [1] 指向字符串中的第二个字符([0] 将是第一个)
  • 为什么标题里写着C++,却把问题标记为C?
  • 您应该将其标记为 MSVC,因为 gcc(至少 >= 4)会警告您将 char const [] 分配给 char * 已被弃用...正如您所见,这是有充分理由的。

标签: c++ c pointers crash


【解决方案1】:

您在函数中返回的字符串通常存储在进程的只读部分中。尝试修改它会导致访问冲突。 (编辑:严格来说,这是未定义的行为,在某些系统中它会导致访问冲突。谢谢,约翰)。

这种情况通常是因为字符串本身与您的应用程序代码一起被硬编码。加载时,指针会指向您的进程中保存文字字符串的那些只读部分。事实上,每当您在 C 中编写一些字符串时,它都会被视为 const char*(指向 const 内存的指针)。

【讨论】:

  • 你不能说它会导致访问冲突。 C++ 对访问冲突一无所知。你真正能说的是它会引发未定义的行为
  • @John:你是对的。那么就从哲学的意义上来说吧:)
  • @John:也许“will”太字符串了,但你很有可能会:-)
  • @rstevens:在 Windows 上它可能是 GPF。在linux上它可能会出现段错误。在我的手机上,它可能会打电话给我妈妈。重点是它的UB。
【解决方案2】:

该函数的签名确实应该是 constchar* Function();

【讨论】:

  • 它实际上应该是std::string,因为 OP 想要修改从函数返回的值
  • 是的,John,在 C++ 中——当然,在 C 中——这是唯一的方法。
【解决方案3】:

您正在尝试修改字符串文字。根据标准,这唤起了undefined behavior。要记住的另一件事(相关)是字符串文字始终是const char* 类型。将指向字符串文字的指针转换为char* 有一个特殊的规定,去掉了const 限定符,但底层字符串仍然是const。因此,通过执行您正在执行的操作,您正在尝试修改 const。这也会引发未定义的行为,类似于尝试这样做:

const char* val = "hello";
char* modifyable_val = const_cast<char*>(val);
modifyable_val[1] = 'n';  // this evokes UB

不要从您的函数中返回 const char*,而是按值返回 string。这将基于字符串文字构造一个新的string,调用代码可以为所欲为:

#include <string>

std::string Function1()
{ 
return “Some text”;
}

...稍后:

std::string s = Function1();
s[1] = 'a';

现在,如果您尝试更改 Function() 返回的值,那么您将不得不做其他事情。我会使用一个类:

#include <string>
class MyGizmo
{
public: 
  std::string str_;
  MyGizmo() : str_("Some text") {};
};

int main()
{
  MyGizmo gizmo;
  gizmo.str_[1] = 'n';
}

【讨论】:

    【解决方案4】:

    您可以使用静态 char 字符串作为返回值,但您从不使用它。这就像访问冲突错误。它的行为在 c++ 标准中没有定义。

    【讨论】:

    • 当然你可以使用它。你只是不能修改它的内容。
    • 哦,没错。还有一件事(就像工作...
    【解决方案5】:

    不是括号,而是赋值。您的函数返回的不是简单的 char *,而是 const char *(我在这里可能是错误的,但这里的内存是只读的),因此您尝试更改不可更改的内存。还有括号 - 它们只是让您可以访问数组的元素。

    【讨论】:

      【解决方案6】:

      另请注意,您可以通过将文本放在常规数组中来避免崩溃:

      char Function1Str[] = "Some text";
      
      char *Function1()
      {
          return Function1Str;
      }
      

      【讨论】:

        【解决方案7】:

        题主看不懂字符串字面量。

        将此代码映像

        char* pch = "Here is some text";
        char* pch2 = "some text";
        char* pch3 = "Here is";
        

        现在,编译器如何为字符串分配内存完全是编译器的事情。内存可能是这样组织的:

        Here is<NULL>Here is some text<NULL>
        

        pch2 指向 pch 字符串内的内存位置。

        这里的关键是理解记忆。使用标准模板库 (stl) 将是一个很好的做法,但您的学习曲线可能相当陡峭。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-10
          • 1970-01-01
          相关资源
          最近更新 更多