【问题标题】:Why does that works in c++ char arrays [duplicate]为什么这在c ++ char数组中有效[重复]
【发布时间】:2015-01-29 15:39:41
【问题描述】:

我有下一个代码:

    char arr[6] = "Hello";
    strcpy(arr, "Hello mellow");
    cout << strlen(arr) << ", " << arr << endl; // 12, Hello mellow


    char arr1[] = "Hello";
    strcpy(arr1, "Hello mellow");
    cout << strlen(arr1) << ", " << arr1 << endl; // 12, Hello mellow

那么,为什么会这样呢?为什么它不以某种方式受到限制?无论我输入什么而不是“Hello mellow”,它都能正常工作并打印出来。

【问题讨论】:

  • 它有时可以工作,但也可能不会甚至崩溃程序。
  • 你很幸运(或没有)。
  • Why doesn't it get limited somehow? 你问的那个问题就是你问题的答案。 “以某种方式受到限制”是什么意思?崩溃?突然弹出一条消息说“你做了一件坏事”?什么都没有发生?这就是未定义行为的含义。我们中的任何一个人,甚至您自己都不知道“以某种方式受到限制”是什么意思——它对任何人都可能意味着任何事情。

标签: c++ c arrays char


【解决方案1】:

之所以有效,是因为strcpy 不会检查目标数组是否至少与源数组一样大。当您使用无效参数调用 strcpy 时,您的代码会调用未定义的行为,并且由于行为未定义,因此任何事情都可能发生;在您的情况下,内存被静默覆盖。您的程序也可能崩溃。

【讨论】:

  • 嗯,大多数现代(全部?)操作系统不会因此崩溃。
  • @BartFriederichs 可能不会。我对内部工作不是很熟悉。
  • @BartFriederichs 仍然是 UB
  • @Columbo,因为他们使用称为“受保护的内存”的东西,每个程序都在自己的内存部分中运行。程序可能会崩溃,但 PC 可能不会。
  • 绝对是 UB,但肯定没有操作系统崩溃。如果是这样,那将是一种非常简单的 DoS 机器方法。
【解决方案2】:

通常,C 和 C++ 不检查边界(与其他高级语言不同:Java、PHP、Python、Javascript 等)。

这意味着,如果您尝试将strcopy(例如,"Hello mellow" 之类的 13 字节字符串)转换为字符数组,它不会检查给定数组是否包含已用足够的内存实例化以包含该字符串。它只会将给定的字符串逐个字符地复制到给定的内存指针中。

这里发生的情况是,您在内存中的某些地方写入了您不应该访问的地方;偶尔,这个程序可能会崩溃,除了:segmentation fault之外没有其他迹象。

如果你碰巧试试这个……

char arr1[8];
char arr2[8];
strcpy(arr1,"Hello mellow");
printf("%s\n", arr1);
printf("%s\n", arr2);

...很有可能(但不是 100% 肯定,请参阅 cmets)您会得到以下输出:

Hello mellow
llow

为什么?因为第二个char[] 会被您尝试放入第一个的数据覆盖,而没有足够的保留空间。

见:http://en.wikipedia.org/wiki/Stack_buffer_overflow

【讨论】:

  • 为什么提到堆栈溢出?
  • 或任何其他输出,因为它是 UB
  • accu.org/index.php/journals/1857 - “恶魔可能会飞出你的鼻子”
  • @NoIdeaForName 这就是我写“很可能”的原因 :) 但是,大多数编译器会彼此相邻地保留内存块。
  • @doctorlove : 非常好的文章 :)
【解决方案3】:

C/C++ 中的原生数组是非常低级的抽象,在许多用例中被视为指向内存位置的指针。因此,当将arr 传递给strcpy 时,所有strcpy 都知道arr[0] 的地址。因此,不可能进行边界检查。出于性能原因,这是一件非常好的事情。程序员有责任确保他/她安全地使用这些低级结构,例如使用strncpy 并给出适当的界限,或使用std::vector 并显式检查界限或使用std::vector::at 来检查访问位置时的边界。

【讨论】:

    【解决方案4】:

    我认为这是因为没有检查运行时或编译时间,如果你很幸运,你不会遇到分段错误;)

    【讨论】:

    • 不幸在我看来没有得到分段错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多