【问题标题】:C++ - Unexpected output from std::stringC++ - 来自 std::string 的意外输出
【发布时间】:2019-04-05 13:01:18
【问题描述】:

我正在编写一个返回字符串的函数。但是奇怪的事情发生了。 result 字符串的输出被控制台打印为意外。

根据机器(TESTED),它变成中文或其他内容或 EMPTY STRING。但这仅在输入字符串超长时才会发生。它通常适用于较小的字符串。

有没有更好的方法将char 附加到字符串?这是因为我怀疑问题是由我将字符添加到字符串末尾的方式引起的。

从控制台

来自调试器

ma​​in.cpp

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

bool checkPalindrome(string s)
{
    return (s == std::string(s.rbegin(), s.rend()));
}

string longestPalindrome(string s)
{
    if (s.size() > 1000 || s.empty())
        return "";

    string result = "";
    string sub = "";
    char* ptr = &sub[0];

    for (int i = 0; i < s.length(); ++i) {
        sub += s[i];
        while (true) {
            string temp = ptr;
            if (checkPalindrome(temp)) {
                ptr = &sub[0];
                if (temp.length() > result.length()) {
                    result = temp;
                    break;
                }
                break;
            }
            else {
                ptr++;
            }
            if (ptr == &sub[sub.length()-1]) {
                ptr = &sub[0];
                break;
            }
        }
    }
    std::cout << "end of function" << std::endl;
    return result;
}



int main()
{
    string output = longestPalindrome("babaddtattarrattatddetartrateedredividerb");
    std::cout << output << std::endl;

    return 0;
}

【问题讨论】:

  • 这不会编译,因为outputmain 中的一个局部变量,但是您以某种方式在longestPalindrome 中访问它。请发布实际的编译代码。
  • 为什么不for (auto character : s)
  • @Blaze 对此感到抱歉。我只是想使用相同的 vairbale 名称进行 aovid,然后将函数 longestPalindrome 中的局部变量 output 更改为 result。我更新了帖子
  • string sub = ""; char* ptr = &amp;sub[0];这不会导致UB吗?
  • &amp;sub[0] 在空字符串上不是 UB:eel.is/c++draft/strings#string.access-1

标签: c++ c++11 c++14 c++17


【解决方案1】:

表达式char* ptr = &amp;sub[0]; 给你一个指向char 的指针。但是,当您执行sub += s[i]; 时,您可能需要string 的内部存储空间增长以容纳新角色。如果你继续添加它,最终它会发生。这将使ptr 无效并使其在重新分配之前无法使用。

当这种重新分配确实发生时,分配了更大的缓冲区,先前的值从较短的缓冲区移动到较大的缓冲区,然后较短的缓冲区被销毁以被较大的缓冲区替换。但是ptr 仍然指向先前较短缓冲区的数据所在的位置。它现在指向一个被破坏对象的元素。然后,当您执行 string temp = ptr; 时,您可能会从无效的指针初始化 string,这是未定义的行为。

一个相对简单的解决方案是坚持使用索引而不是指针。只要索引在string 的大小范围内,它们就不会失效。另一种可能的解决方案可能是使用reserve 预分配足够大的容量,使其永远不必重新分配。

【讨论】: