C ++ - неожиданный вывод из std :: string - PullRequest
3 голосов
/ 05 апреля 2019

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

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

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

Из консоли

enter image description here

От отладчика

enter image description here

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 = &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;
}

1 Ответ

6 голосов
/ 05 апреля 2019

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

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

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

...