Проверка, можно ли освободить указатель - PullRequest
5 голосов
/ 01 января 2011

Я искал ответ на этот вопрос, но, похоже, не нашел его.(У меня довольно ограниченный опыт работы с C ++)

В моей библиотеке я освобождаю строку.(Удивительно, да?)

Вот здесь и возникает проблема.У меня есть структура, которая содержит символ *, который может быть выделен в куче или не может быть.Хотя это допустимый указатель, он не может быть освобожден.

IE

char* s1 = "A String";
char* s2 = (char*)memcpy(malloc(9), s1, 9);

free(s2);
free(s1);

Приведет к ошибке "free (s1);"(Как и должно быть) Поскольку s1 на самом деле не нужно для освобождения, (это не в куче), как я могу справиться с этим "приемлемым" способом?(По аналогичным темам ответ «пусть это рушится» не показался разумным ИМО)

Поскольку структура создается не только библиотекой, невозможно гарантировать, что строка будет правильно скопированаиспользуя что-то вроде memcpy.

Поскольку это библиотека Windows, мне не нужно беспокоиться об использовании ISO C или стандартных функций C.

Ответы [ 7 ]

6 голосов
/ 01 января 2011

В C ++ вам не нужно беспокоиться об этом вообще.Используйте std::string и он автоматически управляет памятью. Не управляйте памятью вручную.

Если бы вы делали это вручную, вам бы пришлось управлять ресурсом самостоятельно,

  • , чтобы сделать пользователябиблиотека управляет памятью самостоятельно, или
  • , требуя от пользователя рассказать вам, как управлять памятью, или
  • , сообщая пользователю, как вы собираетесь управлять памятью, а затем ожидаете, что пользовательсоблюдать.
2 голосов
/ 01 января 2011

Поскольку это библиотека Windows, укажите аргумент BSTR.Затем вы требуете, чтобы пользователь выделил его правильно (с SysAllocString), и вы гарантированно используете соответствующий освобождающий ключ .

Другие методы просто ... плохой.Если у вашего пользователя другой компилятор, вы не сможете free() строку, даже если он действительно использовал malloc.

[Примечание: конвертировано из комментария по запросу Джеймса, это действительно просто Windowsконкретный случай последнего из его предложений ]

Примечание: BSTR - это Unicode.Я вроде как помню, что видел способ использования распределителя BSTR для хранения строк ANSI, кажется, что SysAllocStringByteLen делает это, но предупреждаю, что помещение данных ANSI в BSTR будет крайне нелогичным для любого, кто знаком с BSTR.

0 голосов
/ 01 января 2011

Для вещей, связанных с выделением памяти в C ++, умные указатели просто великолепны. Просто говорю.

http://www.cplusplus.com/reference/std/memory/auto_ptr/

http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/smart_ptr.htm

0 голосов
/ 01 января 2011

В прошлом я делал нечто подобное, когда в некоторых случаях я использовал строку, выделенную в стеке, и строку, выделенную в куче, но в конечном итоге они передавались в другой общий код.

Что я сделал в этом случае, так это наличие двух указателей. Один из них - NULL или строка, выделенная в куче. Другой указатель указывает либо на выделенную в стеке, либо на ту же память, выделенную в куче, что и предыдущая. Когда вы отправляетесь в free (), вы проверяете только прежний указатель.

Конечно, это будет выглядеть неприятно в открытом API. В моем случае это был только внутренний код.

0 голосов
/ 01 января 2011

Храните все строки в куче, тогда вы будете знать, что все они должны быть освобождены. Если строка существует как в глобальной памяти, скопируйте ее в буфер кучи.

0 голосов
/ 01 января 2011

Это то, что известно во время компиляции.Вы смотрите на код и знаете, что бесплатно, а что нет.Так что не думайте о способе отложить его до времени выполнения, потому что кроме того факта, что в этом случае вы не найдете пути, это неправильный способ делать вещи в C ++.Когда вы можете делать это статически, делайте это статически.

Используйте систему типов.Используйте RAII.

0 голосов
/ 01 января 2011

Вы можете malloc char *s1 и поместить "A String" в качестве значения. После этого вы можете бесплатно s1.

...