Страница 1 из 2

Malloc free() в функцие.

Добавлено: 07 окт 2009, 12:23
LifeStyle
Помогите плиз
если у меня есть какаято функция в которой я использую маллок и она возвращает этот массив в main например. как я использую free();???

Re: Malloc free() в функцие.

Добавлено: 07 окт 2009, 18:01
Romeo
Такой код? А в чём проблема?

Код: Выделить всё

void main()
{
   int* arr = get_array_allocated_with_malloc();
   free(arr);
}

Re: Malloc free() в функцие.

Добавлено: 07 окт 2009, 19:34
LifeStyle
Romeo писал(а):Такой код? А в чём проблема?

Код: Выделить всё

void main()
{
   int* arr = get_array_allocated_with_malloc();
   free(arr);
}
нет я имел ввиду к примеру такой код:

Код: Выделить всё

char *CH(char *s){
   char *str;
   str=(char*)malloc((int)strlen(s)*sizeof(char));
 return str;
}
как использовать free(); в данной ситуации?!

Re: Malloc free() в функцие.

Добавлено: 07 окт 2009, 22:48
Romeo
Ну, собственно, мой предыдущий код является ответом на твой вопрос. Внесу изменения, чтобы стало понятней.

Код: Выделить всё

#include <stdio.h>
#include <conio.h>
#include <string.h>

char* copy_string(const char* sz)
{
   char* ret = (char*)malloc((strlen(sz) + 1) * sizeof(char));
   strcpy(ret, sz);
   return ret;
}

void main()
{
   char str[64];
   scanf("%s", str);
  
   char* cs = copy_string(str);
   printf("Copied string is '%s'\n", cs);
   free(cs);

   getch();
}

Re: Malloc free() в функцие.

Добавлено: 08 окт 2009, 00:23
LifeStyle
Romeo писал(а):Ну, собственно, мой предыдущий код является ответом на твой вопрос. Внесу изменения, чтобы стало понятней.

Код: Выделить всё

#include <stdio.h>
#include <conio.h>
#include <string.h>

char* copy_string(const char* sz)
{
   char* ret = (char*)malloc((strlen(sz) + 1) * sizeof(char));
   strcpy(ret, sz);
   return ret;
}

void main()
{
   char str[64];
   scanf("%s", str);
  
   char* cs = copy_string(str);
   printf("Copied string is '%s'\n", cs);
   free(cs);

   getch();
}
Спасибо огромное вот именно это я и хотел узнать))))

Re: Malloc free() в функцие.

Добавлено: 09 окт 2009, 05:20
atavin-ta
А здесь наглядное пособие, как делать не надо

Код: Выделить всё

char* copy_string(const char* sz)
{
  char* ret = (char*)malloc((strlen(sz) + 1) * sizeof(char));
  strcpy(ret, sz);
  free(ret);
  return ret;
}
Сравни оба кода и никогда не делай так, как я только что написал.
Судя по факту существования таких тем, надо ввести специальные темы или подразделы во всех разделах по языкам и назвать их "борьба с утечками памяти". А всех, кто будет спрашивать про free, delete и тому подобные операторы и функции, отсылать в эти темы.

Re: Malloc free() в функцие.

Добавлено: 10 окт 2009, 13:20
LifeStyle
atavin-ta писал(а):А здесь наглядное пособие, как делать не надо

Код: Выделить всё

char* copy_string(const char* sz)
{
  char* ret = (char*)malloc((strlen(sz) + 1) * sizeof(char));
  strcpy(ret, sz);
  free(ret);
  return ret;
}
Сравни оба кода и никогда не делай так, как я только что написал.
Судя по факту существования таких тем, надо ввести специальные темы или подразделы во всех разделах по языкам и назвать их "борьба с утечками памяти". А всех, кто будет спрашивать про free, delete и тому подобные операторы и функции, отсылать в эти темы.
спасибо за пример но все же неправильность твоего кода я знал и понимал потому и спросил этот вопрос потому что думал так как Romeo написал это тоже не правильно... а оказалось иначе))спасибо еще раз за пример повторение мать учение))))

Re: Malloc free() в функцие.

Добавлено: 12 окт 2009, 09:24
atavin-ta
LifeStyle писал(а):спасибо за пример но все же неправильность твоего кода я знал и понимал потому и спросил этот вопрос потому что думал так как Romeo написал это тоже не правильно... а оказалось иначе))спасибо еще раз за пример повторение мать учение))))
Хорошо, что еще понимал. Мне попадалось (уже не помню, где) упоминание некой книги (не помню, чьей и как называется), где код с похожей ошибкой якобы приведён в качестве правильного. Причём, это была критика книги с разбором ошибки. Там было сказано, что к моменту return указатель уже не существует и в результате возвращается полный бред. Вот я и счёл не лишним дать и такой пример. В коде же Romeo ошибок нет. К моменту return указатель еще существует и он возвращается. Для вызывающей функции нет никаких запретов на какие либо операции с указателем, включая и его удаление. Эта функция вызывает free, а она удаляет указатель (для неё запреты тем более не существуют). И даже то, что указатель объявлен внутри функции, ничего не меняят, так как при возврате значения указатель копируется из локальной памяти в глобальную. Ошибка в моём коде - возврат указателя на локальный обект. У Romeo локальный указатель на глобальный объект копируется в глобальный указатель на тот же глобальный объект, а free интересует только содержащийся в указателе адрес, а не сам указатель.
Альтернативный вариант:

Код: Выделить всё

void copy_string(char *p,const char* sz)
{
 strcpy(p, sz);
 return p;
}
int min ()
{
 char *p;
 p = (char*)malloc((strlen(sz) + 1) * sizeof(char)); 
 if (p)
 { 
  copy_string(p,sz);
  free(p);
 }
}
допустим, но не желателен, так как функция copy_string может быть по ошибке вызвана с недействительным указателем. Лучше всего, все указатели создавать только внутри самих уфункций, которые по этим указателям размещают какие-то данные. Но если сама функция хочет что-то по указателю получить, тогда ей надо передать указатель в качестве параметра.

Re: Malloc free() в функцие.

Добавлено: 13 окт 2009, 00:18
Romeo
Вижу, что старался, но написано достаточно много, язык тяжёлый и по всему тексту неточности.
&quot писал(а):указатель еще существует
Нельзя говорить "указатель существует", "удаляем указатель". Это грубейшее нарушение терминологии, которое как раз ведёт к указанным выше непониманиям. Как только мы начнём говорить вместо этого "память существует", "удаляем память", как сразу всё становится на свои места и нужда в подобных громоздких объяснениях тотчас же отпадает.
&quot писал(а):И даже то, что указатель объявлен внутри функции, ничего не меняят, так как при возврате значения указатель копируется из локальной памяти в глобальную
Тут я даже не знаю что сказать. Не расскажешь мне где эта глобальная память расположена? :)

На самом деле всё обстоит намного проще. Функция malloc выделяет память в heap'е и возвращает указатель на эту память. Указатель мы записываем в локальную переменную и работаем с ним. В момент выхода из функции мы пишем return и возвращаем указатель. Так, как указатель - это всего лишь переменная, хранящая адрес, то она без каких бы то ни было пробле помещается в регистр EAX, затем функция завершается. После выходы из функции, во внешнюю переменную cs записывается значение, храняшееся в EAX и мы вновь можем работать с участком памяти, адрес которого только что был возвращён из функции copy_string. С момента выхода из функции и до вызова free уже внутри функции main память, выделенная в heap'е, никак не менялась. Все манипуляции были связаны лишь с передачей адреса этой памяти. Никакой "глобальной памяти, в которую копируется указатель" нет, не было и не будет.
&quot писал(а):Ошибка в моём коде - возврат указателя на локальный обект
От того, что ты перенёс вызов free внутрь функции copy_string, память, выделенная с помощью malloc, не станет локальной. И в твоём, и в моём примере, память размещена в heap'e, то есть она динамическая. Ошибка в твоём коде совсем в другом: в возврате указателя на удалённую память, которую наверняка кто-то снаружи захочет прочитать.
&quot писал(а):а free интересует только содержащийся в указателе адрес, а не сам указатель.
Тотально неверная терминология, либо, как вариант, тотально неверное понимание сути. Если ты внимательно прочитал то мои предыдущие комментарии, то сам должен понять почему это так.

Кстати, вариант с внешним malloc наоборот более предпочтителен. Есть рекомендация располагать вызовы парных функций (например malloc и free) в одном уровне вложенности. Это позволяет легче отлавливать ошибки типа "забыт вызов парной функции". Но это уже другая тема для обсуждения...

Re: Malloc free() в функцие.

Добавлено: 13 окт 2009, 10:59
atavin-ta
&quot писал(а):Нельзя говорить "указатель существует", "удаляем указатель". Это грубейшее нарушение терминологии, которое как раз ведёт к указанным выше непониманиям. Как только мы начнём говорить вместо этого "память существует", "удаляем память", как сразу всё становится на свои места и нужда в подобных громоздких объяснениях тотчас же отпадает.
Спасибо за подсказку.
&quot писал(а):Тут я даже не знаю что сказать. Не расскажешь мне где эта глобальная память расположена?
Для совремнноей винды это тоже теримнологически не точно. Вся память на самом деле глобальна, а локальной нет. Имеется же ввиду память для глобальных данных и память для локальных данных (то есть принадлежащая функции часть стека). Наверное, такие неточности действительно могут затуманикать смысл, раз уж ты меня не полял. Так что ты правильно сдела, что указал на плохую формулировку. Впредь буду формулировать точнее. А уже написанное читай. подставляя "область памяти, предназначенная для хранения глобальных данных программы из глобальной области видимости", а вместо "локальная память" - "память, предназныченная для хранения данных из локальной области видимости (стек)". И в данном случае даже это не совсем верно. В данном случае вместо "глобальная память" читай "память, предназныченная для хранения данных из области видимости функции main", а вместо "локальная память" - "память, предназныченная для хранения данных из области видимости функции, вызываемой из main".
&quot писал(а):От того, что ты перенёс вызов free внутрь функции copy_string[.b], память, выделенная с помощью malloc, не станет локальной.
Какова реальная область видимости? Во-первых, указатель, полученный при выделении памяти, сохранён в локальной перемнной. Во-вторых, сам обект создан после вызова функции и до вызова не вилден. В-третьих, после удаления памяти, объект не существует. Следовательно, в этот момент обект выходит из области видимости. Значит он локален, хотя и создаётся в глобальной памяти, то есть в памяти, доступ к которой может быть предоставлен другому приложению. Кстати, не я придумал называть этот вид ошибки "возвратом указателя на локальный объект". Именно так она и была названа в той критике.