Как удалить символ * в C ++

Каждый раз, когда я выполняю это ... я получаю сообщение об ошибке:

char * var= new char[256];
var= "hola mundo\0";
delete var;

я получаю ошибку:

malloc: *** ошибка для объекта 0x10007fd20: освобождаемый указатель не был выделен
*** установить точку останова в malloc_error_break на

Я не хочу использовать std :: string или std :: vector ... потому что я использую в нескольких функциях char * в качестве параметра, и я хотел бы иметь возможность его уничтожить.


person DaWNFoRCe    schedule 12.06.2014    source источник
comment
Две ошибки - strcpy(var, "hola mundo"); вместо assign и delete[] var; вместо delete   -  person keltar    schedule 12.06.2014
comment
Вам действительно стоит использовать std :: string. Одна причина: вы не можете назначать такие строки. Для строк в стиле c вам нужно использовать strcpy или strncpy, strcat или strncat '.   -  person Joe    schedule 12.06.2014
comment
Я не хочу использовать std :: string, потому что в нескольких функциях я использую char * в качестве параметра - а потом? вы никогда не слышали о методе std::string::c_str()?   -  person The Paramagnetic Croissant    schedule 12.06.2014
comment
Что ж, std::string::c_str() возвращаемое значение - const char*, его нельзя изменять (даже с const-cast, это нарушит внутреннюю структуру строк, такую ​​как длина и емкость), поэтому это не всегда подстановочная замена.   -  person keltar    schedule 12.06.2014
comment
@keltar, затем &str[0]. Это можно изменить.   -  person The Paramagnetic Croissant    schedule 12.06.2014
comment
@ user3477950, я полагаю, то же самое, что и c_str с константным приведением. Как бы вы обновили length() после изменения строки?   -  person keltar    schedule 13.06.2014
comment
@keltar Вы не обновляете его после изменения. Вы resize() это сначала , только потом копируете.   -  person The Paramagnetic Croissant    schedule 13.06.2014


Ответы (3)


Когда у вас есть var= "hola mundo\0";, который присваивается строке в памяти, которую резервирует компилятор. Вызов delete по этому поводу - неопределенное поведение. Кроме того, есть утечка оригинального var, поскольку это никогда не deleted. Вы должны сделать что-то вроде использования strcpy, чтобы скопировать вашу строку в var, или использовать std::string, чтобы не беспокоиться о ее освобождении. Пример: std::string var = "hola mundo";

person edtheprogrammerguy    schedule 12.06.2014
comment
извините, чувак, но поскольку параметризация не использует строку в качестве стандартного типа возвращаемых данных, а char * Мне нужно уничтожить то, что вы видите там ... без использования строки ... в любом случае спасибо! - person DaWNFoRCe; 13.06.2014

Значение указателя, полученное вами от new, теряется, когда вы назначаете что-то еще для var. Исходное содержимое var исчезло. Затем вы пытаетесь удалить что-то еще.

person ScottMcP-MVP    schedule 12.06.2014
comment
куда пропало == утечка - person Paul Roub; 12.06.2014
comment
да ... я знаю ... но я все еще хочу уничтожить литерал, присвоенный var ... какие-нибудь идеи? - person DaWNFoRCe; 13.06.2014
comment
Невозможно. Это часть вашего exe-файла только для чтения, как и код вашей программы. - person ScottMcP-MVP; 13.06.2014

Во-первых, присвоение строкового литерала переменной char* не копирует строковые данные в выделенную вами память. Вместо этого он просто переназначает указатель, чтобы var больше не указывал на выделенную вами память. Это означает, что выделенная вами память теряется и никогда не освобождается должным образом, и это означает, что вы используете delete с указателем, который вы никогда не выделяли, что является недопустимым.

Во-вторых, вы выделяете массив с помощью new char[], поэтому вам нужно использовать delete [] вместо просто delete.

В-третьих, строковые литералы автоматически включают нулевой терминатор, поэтому вам не нужно добавлять лишний:

var = "hola mundo";

Наконец, если вы можете использовать C ++ 11 или C ++ 14, вам не следует использовать new и delete напрямую. В более ранних версиях C ++ во многих случаях можно по-прежнему избегать new и delete. В этом случае, поскольку уже существует тип std::string, вы должны просто использовать его независимо от того, какую версию C ++ вы используете. Ваши три строки кода следует заменить на:

std::string var = "hola mundo";

Это проще и безопаснее.

person bames53    schedule 12.06.2014
comment
Привет, спасибо, я, по-видимому, забыл [] :( плохо, но, как я уже упоминал, многие библиотеки используют char * вместо строки для передачи значений через функции, которые позже необходимо уничтожить !!! Так что вы не можете использовать строку в этих случаях !! Итак, как я сказал в посте ... и как это правда в реальной жизни ... Я не могу использовать строку ... какие-нибудь идеи? - person DaWNFoRCe; 13.06.2014
comment
@DaWNFoRCe вы по-прежнему можете использовать std::string как для передачи char* данных, так и для управления char* буферами, заполненными библиотекой. Если вы имеете в виду, что вы написали функции, которые принимают char*, и этим функциям необходимо освободить переданный буфер, тогда это может создать проблему для std::string, но это также плохая идея по нескольким причинам. - person bames53; 13.06.2014
comment
Извините, но мне не ясно, как я создаю дыру нового типа строки объекта ... чтобы уничтожить тот, на который указывает char . Нет, я не делаю этого позже ... Я вызываю функции, которые возвращают char ... а затем мне нужно их уничтожить, вот и все ... - person DaWNFoRCe; 14.06.2014
comment
@DaWNFoRCe О, если библиотека выделяет строку, а у вас нет контроля над распределением, тогда, очевидно, вам нужно делать все, что требует библиотека, чтобы освободить строку. Конечно, это плохо спроектированная библиотека, и вы еще можете кое-что сделать. Вы должны немедленно передать выделенную память интеллектуальному указателю. Например, unique_ptr<char[]> buf(foo());, и вы можете даже захотеть немедленно скопировать данные в более разумный тип, например std::string. Например. unique_ptr<char[]> buf(foo()); std::string copy = &buf[0];. - person bames53; 14.06.2014
comment
Конечно, если библиотека выполняет выделение, она должна сообщить вам, как правильно освободить. Запрос на stackoverflow не скажет вам, что требуется библиотеке. Библиотека может потребовать delete, delete[], custom_library_deallocator(), free() и т. Д. Вы должны прочитать документацию библиотеки. - person bames53; 14.06.2014
comment
Опять же ... я не думаю, что это первый раз ... и библиотеки, когда они отправляют простые типы данных, такие как указатели символов ... ну, они ожидают, что вы знаете, как освободить лок ... Я честно могу сказать, что не ... как удалить указатель char * ... простой вопрос ... помощь! - person DaWNFoRCe; 16.06.2014
comment
Библиотеки не могут просто «ожидать, что вы знаете» правильный метод освобождения, потому что библиотека определяет правильный метод, и они могут выбрать более одного варианта. Как я уже сказал, библиотека может использовать malloc () (что означает, что вы используете free (), или она может использовать new [] (что означает, что вы используете delete []) и т. Д., Обратитесь к документации библиотеки. - person bames53; 16.06.2014