C — Неожиданный вывод из std::string

#c #c 11 #c 14 #c 17

#c #c 11 #c 14 #c 17

Вопрос:

Я пишу функцию, которая возвращает строку. Но произошло что-то странное. Вывод result строки был напечатан как неожиданная вещь с консоли.

Он становится китайским или чем-то другим или ПУСТОЙ строкой в зависимости от машины (ПРОТЕСТИРОВАНО). Но это происходит только тогда, когда входная строка очень длинная. Это работает нормально для строк с меньшим размером.

Есть ли лучший способ добавить char к строке? Это потому, что я подозреваю, что проблема была вызвана тем, как я добавил символы в конец строки.

Из консоли

введите описание изображения здесь

Из отладчика

введите описание изображения здесь

main.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 = amp;sub[0];

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



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

    return 0;
}
  

Комментарии:

1. Это не компилируется, потому что output является локальной переменной в main , но вы каким-то образом получаете к ней доступ longestPalindrome . Пожалуйста, опубликуйте фактический, компилируемый код.

2. почему бы и нет for (auto character : s)

3. @Blaze извините за это. Я просто хотел, чтобы aovid использовал то же имя vairbale, а затем изменил локальную переменную output на result в функции longestPalindrome . Я обновил сообщение

4. string sub = ""; char* ptr = amp;sub[0]; Не приведет ли это к UB?

5. amp;sub[0] в пустой строке нет UB: eel.is/c draft/strings#string.access-1

Ответ №1:

Выражение char* ptr = amp;sub[0]; дает вам указатель на char . Однако при выполнении sub = s[i]; вам может потребоваться, чтобы внутренняя память string увеличилась, чтобы вместить новый символ. Если вы продолжаете добавлять к нему, в конечном итоге это произойдет. Это сделает его недействительным ptr и сделает его непригодным для использования до тех пор, пока он не будет переназначен.

Когда такое перераспределение действительно происходит, выделяется буфер большего размера, предыдущее значение перемещается из более короткого буфера в буфер большего размера, затем более короткий буфер уничтожается для замены на больший. Но ptr все еще указывает на то, где раньше находились данные предыдущего более короткого буфера. Теперь он указывает на элемент уничтоженного объекта. Когда вы затем это сделаете, string temp = ptr; вы рискуете инициализировать string из недействительного указателя, поведение которого не определено.

Одним из относительно простых решений было бы придерживаться индексов вместо указателей. Индексы по своей природе не становятся недействительными, пока они находятся в пределах размера string . Другим возможным решением может быть использование reserve для предварительного выделения достаточно большой емкости, чтобы ее никогда не приходилось перераспределять.