Почему удаление объекта ostringstream, как в моем коде, приводит к ошибке сегментации?

#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <string>

using namespace std;

int main()
{
    ostringstream out;
    ostringstream tmpstr;
    tmpstr << "ritesh is here";
    out << tmpstr.str().c_str();
    out << endl;
    cout << out.str();
    if(tmpstr.rdbuf()!=NULL)
        cout << "tmpstr not null" <<endl;
    else
        cout << "tmpstr null" <<endl;
    delete tmpstr.rdbuf();   // This line gives me segmentation fault
    cout <<"deleted" << endl;
}

Строка delete tmpstr.rdbuf(); дает ошибку сегментации. Я предполагаю, что rdbuf возвращает указатель char* и, следовательно, . Я могу использовать удаление на нем, чтобы освободить место в памяти, выделенное для tmpstr

Я где-то ошибся?


person Invictus    schedule 11.05.2012    source источник
comment
Получение ресурсов — это инициализация. Знай это. Любить это.   -  person Ed S.    schedule 11.05.2012
comment
@EdS.: Хотя совет хороший, я не понимаю, как он здесь применим.   -  person John Dibling    schedule 11.05.2012
comment
@JohnDibling: Потому что так работает std::string. Если вы это понимаете, тогда вы поймете, что вам не нужно вызывать delete ни для чего здесь. Учитывая, что это концепция более высокого уровня, чем то, о чем просит ОП, но если вы собираетесь использовать string, vector и т. д., вы должны понимать, что происходит за кулисами.   -  person Ed S.    schedule 11.05.2012
comment
Ритешу не нужно ничего знать о RAII или внутренней работе string или vector, чтобы понять, что deleteинг tmpstr.rdbuf(); — это плохо.   -  person John Dibling    schedule 11.05.2012


Ответы (1)


Да вы ошибаетесь, думая, что можно delete то, что вы не выделили.

Только delete вещи, которые вы new создали сами. Не delete чужие вещи.

person John Dibling    schedule 11.05.2012
comment
Nitpick: Только delete вещи, которые были выделены с помощью new. Иногда функция, которую вы не писали, выделяет память, за очистку которой вы несете ответственность. То, что вы не позвонили new, не означает, что вы никогда не позвоните delete. - person Ed S.; 11.05.2012
comment
Не удаляйте чужие материалы, если они не сказали вам сделать это явно в документации. - person Alok Save; 11.05.2012
comment
@Als: Да, это то, к чему я клонил: D - person Ed S.; 11.05.2012
comment
@Als: и если в документации сказано, что это необходимо, ищите альтернативы, которые не так плохо спроектированы. Это должно почти не понадобиться (передача объектов между потоками является разумным исключением). - person Jerry Coffin; 11.05.2012
comment
@JerryCoffin: Удачи с этим. Вы не всегда можете позволить себе роскошь идеально спроектированного API. Кроме того, многие API предназначены для совместимости с C, что означает знание того, что делать с возвращаемыми функциями значениями. - person Ed S.; 11.05.2012
comment
@EdS.: Между идеальным и невежественным есть много места. - person Jerry Coffin; 11.05.2012
comment
@JerryCoffin: Конечно, но по моему опыту (системное программирование) у вас часто нет выбора, и API написаны людьми, которые могут быть в основном специалистами по аппаратному обеспечению ... ну, вы поняли. Конечно, потому что если это так, то я, вероятно, немного предвзят. - person Ed S.; 11.05.2012
comment
@EdS.: Но вряд ли это общий совет в общем случае. - person Puppy; 11.05.2012
comment
@Ed S: Если другой код вызвал новый и вернул указатель, который они хотели, чтобы вы удалили, то он должен возвращать не указатель, а std::auto_ptr‹› (или другой sp), чтобы указать передачу права собственности. Кроме того, в этом случае вы должны не вызывать удаление, а позволить интеллектуальному указателю выполнять свою работу. Поэтому я отвергаю вашу гипотезу как неверную. Указатель, возвращенный из кода, который не принадлежит вам, не должен быть удален (любая документация, показывающая, что вы должны указывать на плохо написанный код, и вы должны изменить используемую библиотеку и временно предоставить оболочку для этой функции, которая делает оболочку для вас). - person Martin York; 11.05.2012
comment
@LokiAstari: я думаю, вы правы в теоретическом мире, где все существующие API были так хорошо спроектированы. Конечно, это не так, поэтому я отвергаю вашу гипотезу как неверную. Кажется, вы живете в мире фантазий; Я живу в реальном мире, где вы часто застреваете, используя API, который возвращает указатель, за освобождение которого вы несете ответственность. Что вы делаете в своей повседневной работе, что дает вам такую ​​свободу, чтобы всегда находить API, который вы считаете хорошо написанным? Обертка, с которой я согласен (и согласен), но, конечно, в какой-то момент вы все еще освобождаете эту память, вы просто немного перемещаете код. - person Ed S.; 12.05.2012
comment
@LokiAstari: Позвольте мне сказать по-другому; Я занимаюсь драйверами устройств. Много. У вас нет свободы отклонить API как неподходящий. Вы используете его, потому что вас вынуждают. Часто это реальность. - person Ed S.; 12.05.2012
comment
Я очень сомневаюсь, что вся эта разработка угловых случаев и необычных исключений действительно помогает ОП понять, почему deleteing tmpstr.rdbuf() это плохо. - person John Dibling; 12.05.2012
comment
@JohnDibling: Я согласен с этим, и именно по этой причине я отказался от этого преобразования после первого комментария, который вызвал возражение со ссылкой на лучшие практики. Слишком много деталей за слишком короткое время просто создает путаницу. Что нужно OP знаю, что он / он не должен звонить delete по адресу, не возвращенному new, остальная часть собственности и педантичность хорошего дизайна API могут хорошо вписаться в книгу, а не в комментарии, хотя это важно, это не кажется потребность в часе для OP. Обучение - это пошаговый процесс, и слишком много деталей может привести к потере. - person Alok Save; 12.05.2012