Я столкнулся со странной проблемой при попытке получить результат функции строки c_str()
чей результат несовместим с g ++.
Существует функция с именем Test, которая возвращает экземпляр строки. И я хочу использовать char*
введите, чтобы сохранить результат (это необходимо). Как видите, функция проста — возвращает строку «resulttring». Но когда я пытаюсь получить результат, происходит нечто странное.
Результат, который я получил — «» во второй части. Часть первая и часть третья возвращают «строку результатов». Пока это в Visual Studio. Три части одного и того же кода, скомпилированного с g ++, возвращают «строку результата. Давайте также сначала посмотрим на результат:
результат против:
Адрес: 16841988
resultstring
Адрес: 16842096
«здесь пустая строка»
Адрес: 16842060
Адрес: 16842144
Адрес: 16842396
Адрес: 16842396
resultstring
результат g ++
Адрес: 5705156
resultstring
Адрес: 5705156
resultstring
Адрес: 5705156
Адрес: 5705196
Адрес: 5705156
Адрес: 5705156
resultstring
#include <iostream>
#include <string>
using namespace std;
string Test()
{
char a[64] = "resultstring";
return string(a);
}
int main(void)
{
//part one
cout << "address:"<< (unsigned)Test().c_str() << endl;
cout << Test().c_str() << endl;
//part two
char *j = const_cast<char*>(Test().c_str());
cout << "address:"<< (unsigned)Test().c_str() << endl;
cout << j << endl;
cout << "address:" << (unsigned)j <<endl;
//part three
string h3 = Test();
char* j2 = const_cast<char*>(h3.c_str());
cout << "address:"<< (unsigned)Test().c_str() << endl;
cout << "address:"<< (unsigned)h3.c_str() << endl;
cout << "address:" << (unsigned)j2 <<endl;
cout << j2 <<endl;
getchar();
return 0;
}
Теперь у меня три вопроса.
Во-первых, почему результат, соблюдаемый g ++, возвращает все resultstring
в то время как результат Visual Studio возвращает все resultstring
кроме переменной j? Если вы выполните отладку, вы обнаружите, что VC ++ только устанавливает адрес j2
лайк 00 65 73 75 …
который esultstring
с 00
начальный адрес И это не странно, что мы получим «». Это так же, как char* str = "\0something else"
вы всегда получите «». Но вопрос в том, почему это происходит только с j
?
Во-вторых, почему один из адресов (unsigned) Test ().c_str()
отличается от других? Если мы удалим линию string h3 = Test ()
адрес будет все тот же.
В-третьих, это «правильное» поведение Visual Studio, возвращающее «» значение переменной j
? почему это отличается от g ++?
Ждем ваших ответов.
С Уважением,
Kevin
У вас неопределенное поведение. std::string
вернулся Test()
является временным и указатель возвращается c_str()
(Хранится в j
) больше не действует после окончания срока действия временных. Это означает, что все может случиться. Массив, на который указывает указатель, может содержать мусор, это может быть исходная строка или реализация может иметь нулевое окончание в начале. Доступ к нему может вызвать ошибку сегментации или может позволить вам получить доступ к исходным строковым данным. Это может и обычно зависит от разных компиляторов и реализаций стандартной библиотеки.
char *j = const_cast<char*>(Test().c_str());
// The contents pointed to by j are no longer valid and access that content
// is undefined behavior
cout << "address:"<< (unsigned)Test().c_str() << endl;
Адрес отличается между звонками на Test()
потому что он возвращает временный каждый раз, когда вы звоните. Некоторые компиляторы могут оптимизировать это, и / или распределение данных может получить один и тот же блок памяти, но это не гарантируется тем же.
Это совершенно неверно. Вы создаете и уничтожаете временную строку каждый раз, когда вызываете Test()
, Любая попытка получить доступ к памяти с помощью указателя, возвращенного Test().c_str()
после временного уничтожения смысла нет — память уже освободилась. Он МОЖЕТ иметь старые значения (если там ничего не записано перед доступом), но он может иметь что-то также (если он используется повторно до доступа). Это неопределенное поведение.
В случае VC ++ он перезаписывается один раз, а в других — нет. С GCC — это никогда не перезаписывается. Но это чистый шанс. Еще раз — это UB.