【问题标题】:C++:when accessing an empty string's element,there is no error,why?C++:访问空字符串的元素时,没有错误,为什么?
【发布时间】:2017-01-08 21:37:18
【问题描述】:
#include <iostream>
#include <string>
using std::string;
int main(){
    string s;
    std::cout << "size:" << s.size() << " "
                      << "capacity:" << s.capacity() << std::endl;
    std::cout << s[3] << std::endl;
    return 0;
}

我定义了一个空的 string 对象,名为 ss.size()s.capacity() 都是 0,但是在访问元素时 s[3],没有段错误,为什么?

【问题讨论】:

  • 在这种情况下,您可以期待未定义的行为。这可能会或可能不会使您的程序崩溃。这种不确定性正是强烈建议不要这样做的原因!
  • 绝对未定义的行为。可能使这不会崩溃的可能是您正在使用的标准库实现的小字符串优化

标签: c++ string


【解决方案1】:

撇开(正如其他人所解释的)这是 UB 并且(从学术上讲)任何事情都可能发生的事实,在这种特定情况下,您没有遇到分段错误的具体原因是操作系统没有检测您分配的对象之外的所有内存访问——它仅检测您的无效内存访问是so错误的,它完全是0x0或另一页虚拟内存,你的进程没有配备.这是唯一存在的“自动”内存错误检测级别。

除此之外,您的计算机还必须检查每个内存访问,并将其与空闲存储中分配的块映射进行比较(这非常慢;您可以在调试期间使用诸如 电子围栏之类的工具进行此操作valgrind),否则您必须自己添加索引检查(例如,使用 .at() 而不是 [])。

C++ 在某种程度上是一种安全的语言,但是仍然有很多感觉是“简单”的功能,从 C 继承而来,您有责任知道自己在做什么,并且不能依靠您的计算机来完成告诉你什么时候做错了。

【讨论】:

    【解决方案2】:

    当您访问不属于您的内存时,segfault 不一定会发生,它可能发生。

    【讨论】:

      【解决方案3】:

      您正在调用一种称为未定义行为的东西。它可能崩溃,它什么也做不了,它可以做你想做的事。没有什么是保证的。这种行为实际上是“未定义的”。

      【讨论】:

        【解决方案4】:

        因为 C++ 中的许多错误没有明确的影响,而是导致未定义的行为。将不可能的索引传递给std::stringoperator[] 就是此类错误的一个示例。任何事情或任何事情都可能发生。

        这是因为要求编译器创建在运行时执行各种错误检查的程序会严重降低 C++ 在错误检查开销无法接受的使用场景中的可用性。通常,如果您想在 C++ 中进行这样的运行时错误检查,则必须要求(并为此付费)。

        一个相当简单的方法是使用at 成员函数,它是为非法字符串索引抛出异常所必需的。但是,除了在main 中使用丑陋的catch 记录错误并退出之外,您将如何“处理”这样的异常?

        一个非法的字符串索引应该被视为一个bug,它必须被修复,而不是在运行时“处理”。幸运的是,有一些方法可以告诉编译器在运行时添加对错误operator[] 的检测。以下是更多信息:


        请注意,只有size 与确定访问元素是否为未定义行为相关。 capacity 不是。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-06-17
          • 1970-01-01
          • 1970-01-01
          • 2023-04-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-01-05
          相关资源
          最近更新 更多