5

这与 C++ 中的字符串有关。很久没有接触C/C++了;事实上,大约 7 年前,我只在大学的第一年就使用这些语言进行了编程。

在 C 中,为了保存字符串,我必须创建字符数组(无论是静态的还是动态的,这都不重要)。所以这意味着我需要提前猜测数组将包含的字符串的大小。好吧,我在 C++ 中应用了相同的方法。我知道有一个 std::string 类,但我从来没有使用过它。

我的问题是,由于我们从未在 std::string 类中声明数组/字符串的大小,因此在写入时是否会发生缓冲区溢出。我的意思是,在 C 语言中,如果数组的大小为 10,并且我在控制台上键入了超过 10 个字符,那么额外的数据将被写入与数组相邻的其他对象的内存位置。使用 cin 对象时,在 std::string 中是否会发生类似的事情。

使用 std::string 时,我是否必须在 C++ 中事先猜测字符串的大小?

出色地!谢谢大家。这个页面上没有一个正确的答案(提供了很多不同的解释),所以我没有选择任何一个这样的答案。我对前 5 个很满意。保重!

4

6 回答 6

9

根据您用来访问string对象的成员,是的。因此,例如,如果您使用reference operator[](size_type pos)where pos > size(),是的,您会使用。

于 2012-05-01T13:20:13.093 回答
6

假设标准库实现中没有错误,没有。Astd::string总是管理自己的内存。

当然,除非您颠覆std::string提供的访问器方法,并执行以下操作:

std::string str = "foo";
char *p = (char *)str.c_str();
strcpy(p, "blah");

您在这里没有保护,并且正在调用未定义的行为

于 2012-05-01T13:18:08.440 回答
3

std::string 通常可以防止缓冲区溢出,但仍然存在编程错误可能导致缓冲区溢出的情况。当操作引用超出字符串边界的内存时,C++ 通常会抛出 out_of_range 异常而下标运算符 [](不执行边界检查)则不会

将 std::string 对象转换为 C 风格的字符串时会出现另一个问题。如果你使用 string::c_str() 进行转换,你会得到一个正确的以 null 结尾的 C 样式字符串。但是,如果您使用 string::data(),它将字符串直接写入数组(返回指向数组的指针),您将获得一个非空终止的缓冲区。The only difference between c_str() and data() is that c_str() adds a trailing null byte.

最后,许多现有的 C++ 程序和库都有自己的字符串类。要使用这些库,您可能必须使用这些字符串类型或不断地来回转换。在安全性方面,此类库的质量参差不齐。通常最好使用标准库(如果可能)或了解所选库的语义。一般而言,应根据库的使用难易程度、可能发生的错误类型、这些错误发生的难易程度以及可能产生的潜在后果来评估库。参考https://buildsecurityin.us-cert.gov/bsi/articles/knowledge/coding/295-BSI.html

在 c 中,原因解释如下:

void function (char *str) {
       char buffer[16];
       strcpy (buffer, str);
    }
    int main () {
      char *str = "I am greater than 16 bytes"; // length of str = 27 bytes
      function (str);
    }

该程序肯定会导致意外行为,因为 27 字节的字符串 (str) 已复制到仅分配 16 字节的位置(缓冲区)。额外的字节越过缓冲区并覆盖为 FP 分配的空间、返回地址等。这反过来又会破坏进程堆栈。用于复制字符串的函数是 strcpy,它不完成边界检查。使用 strncpy 可以防止这种堆栈损坏。然而,这个经典的例子表明缓冲区溢出会覆盖函数的返回地址,进而改变程序的执行路径。回想一下,函数的返回地址是内存中下一条指令的地址,该指令在函数返回后立即执行。

这是一个很好的教程,可以让您的答案满意。

于 2012-05-01T13:19:09.140 回答
2

在 C++ 中,std::string类以最小大小开始(或者您可以指定起始大小)。如果超出该大小,则std::string分配更多动态内存。

于 2012-05-01T13:18:19.577 回答
1

假设提供的库std::string被正确写入,您不能通过向std::string对象添加字符来导致缓冲区溢出。

当然,库中的错误并非不可能。

于 2012-05-01T13:16:50.613 回答
1

“缓冲区溢出是否发生在 C++ 代码中?”

在某种程度上,C 程序是合法的 C++ 代码(它们几乎都是),并且 C 程序有缓冲区溢出,C++ 程序可能有缓冲区溢出。

比 C 更丰富,我确信 C++ 可以以 C 不能的方式发生缓冲区溢出:-}

于 2012-05-02T11:58:43.160 回答