Функция VC ++ string :: c_str (): адрес первого байта был установлен в 0 (сравните с g ++)

Я столкнулся со странной проблемой при попытке получить результат функции строки 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

0

Решение

У вас неопределенное поведение. 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() потому что он возвращает временный каждый раз, когда вы звоните. Некоторые компиляторы могут оптимизировать это, и / или распределение данных может получить один и тот же блок памяти, но это не гарантируется тем же.

1

Другие решения

Это совершенно неверно. Вы создаете и уничтожаете временную строку каждый раз, когда вызываете Test(), Любая попытка получить доступ к памяти с помощью указателя, возвращенного Test().c_str() после временного уничтожения смысла нет — память уже освободилась. Он МОЖЕТ иметь старые значения (если там ничего не записано перед доступом), но он может иметь что-то также (если он используется повторно до доступа). Это неопределенное поведение.

В случае VC ++ он перезаписывается один раз, а в других — нет. С GCC — это никогда не перезаписывается. Но это чистый шанс. Еще раз — это UB.

3

По вопросам рекламы [email protected]