LINUX.ORG.RU

Ответ на: комментарий от anonymous

>использовать соответствующий метод c_str(), если я правильно помню

Допустим делаю так:

#include <string>
#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
      string mystr("text");
      char * mycstring = new char[mystr.size()];
      mycstring = (char *)mystr.c_str();
      cout << mycstring;
      delete []mycstring;
}

В таком случае содержимое строки вроде как выводится, но при очищении памяти -- сегфолт =/ Что я делаю не так? (просьба не пинать)

anonymous
()
Ответ на: комментарий от anonymous

> это лишнее

т.е. если убрать, утечки не будет?

anonymous
()
Ответ на: комментарий от anonymous

Зачем выделить память и потом затереть указатель?

-      char * mycstring = new char[mystr.size()];
-      mycstring = (char *)mystr.c_str();
+      char * mycstring = (char *)mystr.c_str();

anonymous
()
Ответ на: комментарий от anonymous

>Зачем выделить память и потом затереть указатель?

>- char * mycstring = new char[mystr.size()];

>- mycstring = (char *)mystr.c_str();

>+ char * mycstring = (char *)mystr.c_str();

Ясно, спасибо.

anonymous
()
Ответ на: комментарий от anonymous

- char * mycstring = (char *)mystr.c_str();
+ const char * const mycstring = (const char * const)mystr.c_str();
как то так =)

anonymous
()
Ответ на: комментарий от anonymous

      string mystr("text");
-      char * mycstring = new char[mystr.size()];
-      mycstring = (char *)mystr.c_str();
-      cout << mycstring;
-      delete []mycstring;
+      std::vector<char> mycstringbuf(mystr.begin(), mystr.end());
+      const char * mycstring =  &mycstringbuf[0];
+      cout << mycstring;

anonymous
()
Ответ на: комментарий от anonymous

>>В таком случае содержимое строки вроде как выводится, но при очищении памяти -- сегфолт =/ Что я делаю не так? (просьба не пинать)

Потому что

mycstring = (char *)mystr.c_str();

копирует указатель, а не саму строку. Далее ты

delete []mycstring;

удаляешь _внутренний буфер_ в std::string, а вовсе не mycstring ;) При выходе из main() удаляется длокальный объект mystr, и происходит segfault, т.к. mystr не знает, что кто-то уже потёр его внутренний буфер, и пытается удалить его опять.

Чтобы работало, надо

- char * mycstring = new char[mystr.size()];
- mycstring = (char *)mystr.c_str();
+ char * mycstring = new char[mystr.size()+1];
+ strcpy(mycstring, (char *)mystr.c_str());

alex_custov ★★★★★
()
Ответ на: комментарий от alex_custov

>удаляешь _внутренний буфер_ в std::string, а вовсе не mycstring ;) При выходе из main() удаляется длокальный объект mystr, и происходит segfault, т.к. mystr не знает, что кто-то уже потёр его внутренний буфер, и пытается удалить его опять.
хуже того. То что возвращает c_str не обязано быть началом буфера, выделеного malloc или new[]. Оно даже может быть выделено кастомным аллокатором - так что удалять внутренний буфер нельзя ни вкоем случае.
А в случае примера - скорее всего буфкр не был выделен динамически, а находился на стеке (большенство реализаций STL имеют внутренний буфер в несколько байт (4,8, 16) для ускорения работы с маленькими строками)

anonymous
()
Ответ на: комментарий от wfrr

>Если в сей буфер попытаться что-либо записать, то какие будут результаты?

Смотря сколько запишешь. Если меньше чем размер буфера - всё будет ОК. Больше - получишь сегфолт. Но сигнатура функции
const char* c_str() const
Должна наводить на мысль - что возвращаемые данные не должны быть изменены. C-like type casting зло - так как позволяет скастовать константный уквзатель в неконстантный. Посему лучше юзать static_cast, dynamic_cast. Компилер не далбы static_cast-ом снять константность. А использование const_cast (ровно как и модификатор mutable) лищний раз заставляет задуматся, что может ты не прав в этом куске кода.

anonymous
()
Ответ на: комментарий от wfrr

> Если в сей буфер попытаться что-либо записать, то какие будут результаты?

Плачевные: кривой код который может заглучить в самый неподходящий момент. Например: 

string str1("help");
string str2(str1);

strcpy((char*)str1.c_str(), "hell");

printf("%s\n%s\n", str1.c_str(), str2.c_str()); // или cout << str1 << endl << str2 << endl; -- пофиг.

Компиляем гцц-ом 4-ым, и видим две строки "hell" на выходе. 

Задание на дом: обьяснить, почему так происходит.

Из всего этого следует такой вывод: если c_str(), возвращает const char*, то @ля 100 раз
подумай, какого %уя он возвращает const char* а не char*.

fmj
()
Ответ на: комментарий от wfrr

> Разве конструктор копий не вызывается?

он конечно же вызывается, но поскольку имплементация строк reference counted, то s2 содержит ссылку на тот-же самый буфер данных, что и s1. и если мы его каким-то образом ломает, этот буфер, то естественно, что страдают оба как бы независимых объекта.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от necromant

> Если нужна _копия_ строки то используй strncpy, если нет то используй совет приведённый выше

или сразу strdup(v.c_str())

dilmah ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.