Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.65/34: Рейтинг темы: голосов - 34, средняя оценка - 4.65
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11

Освобождение памяти malloc free

29.03.2013, 22:02. Показов 6973. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В общем работаю над расширением для php (для тренировки в php и в c++ сразу) Суть дела вот в чем, наткнулся на конвертер php массива в массив c++ , суть вот в чем, функция ест память! Я не умею обращаться с ф-й malloc и free и по этомц ситуация поставила меня в тупик.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
void *php_array_to_c_array(zval *param,int type,int size,int *array_size)
{
  HashTable *param_ht = param->value.ht;
  zval **cur;
  void *params;
  void *array;
  int i,tmp_size = zend_hash_num_elements(param_ht);
  int id;
  zend_hash_internal_pointer_reset(param_ht);
  params = (void *)malloc(size * tmp_size);
  i = 0;
  while(zend_hash_get_current_data(param_ht,(void **)&cur) == SUCCESS)
    {
       if((*cur)->type == IS_ARRAY)
          {
              int new_array_size;
              void *array = php_array_to_c_array(*cur,type,size,&new_array_size);
              array = php_array_to_c_array(*cur,type,size,&new_array_size);
              params = realloc(params, (tmp_size + new_array_size) * size);
              memcpy(&((char*)params)[i*size],array,new_array_size * size);
              i += (new_array_size - 1);
              free(array);
          }
       else
          {
              switch(type)
                   {
                        case TO_C_FLOAT:
                            convert_to_double(*cur);
                            ((float*)params)[i] = (float)Z_DVAL_P(*cur);
                        break;
                        case TO_C_DOUBLE:
                            convert_to_double(*cur);
                            ((double*)params)[i] = Z_DVAL_P(*cur);
                        break;
                        case TO_C_INT:
                            convert_to_long(*cur);
                            ((int*)params)[i] = (int)Z_LVAL_P(*cur);
                        break;
                        case TO_C_LONG:
                            convert_to_long(*cur);
                            ((long*)params)[i] = Z_LVAL_P(*cur);
                        break;
                        case TO_C_UCHAR:
                        case TO_C_UBYTE: // yoya
                            convert_to_long(*cur);
                            ((unsigned char*)params)[i] = (unsigned char)Z_LVAL_P(*cur);
                        break;
                        case TO_C_SCHAR:
                            convert_to_long(*cur);
                            ((signed char*)params)[i] = (signed char)Z_LVAL_P(*cur);
                        break;
                        case TO_C_USHORT:
                            convert_to_long(*cur);
                            ((unsigned short*)params)[i] = (unsigned short)Z_LVAL_P(*cur);
                        break;
                        case TO_C_SHORT:
                            convert_to_long(*cur);
                            ((short*)params)[i] = (short)Z_LVAL_P(*cur);
                        break;
                        case TO_C_UINT:
                            convert_to_long(*cur);
                            ((unsigned int*)params)[i] = (unsigned int)Z_LVAL_P(*cur);
                        break;
                        case TO_C_STRING:
                            convert_to_string(*cur);
                            ((char **)params)[i] = estrdup(Z_STRVAL_P(*cur));
                        break;
                   }
          }
       zend_hash_move_forward(param_ht);
       i++;
    }
  if(array_size != NULL)
  *array_size = i;
  return (void *)params;
}
в общем я понял что нужно что-то сделать с переменное params, т.к. память выделяется, но не освобождается. Так что хелп если это возможно))
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
29.03.2013, 22:02
Ответы с готовыми решениями:

Из malloc-free в new delete
Есть код с выделением памяти с помощью malloc, надо сделать с new delete Вроде сделал, освобождение памяти работает, а с выделением...

SIGABRT после free malloc
не могу почистить string array matches (2 dim) проблема возникает на линии 114 отмеченной как //Cleaning up an array не могу почистить...

Управление памятью с использованием malloc и free
int n=3; int * v = (int*) malloc(n*sizeof(int)); // обьявил вектор из 3-х целочисельных елементов v = 0; v = 1; v =...

16
0 / 0 / 0
Регистрация: 29.03.2013
Сообщений: 18
29.03.2013, 23:20
C++
1
2
3
return (void *)params;
free(params);
}
насколько я знаю так
0
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
29.03.2013, 23:28
Systemes, когда функция malloc выделила память, то она вернула указатель на ее начало. Вы не должны его потерять. Когда вы перестаете нуждаться в этой памяти, то ее нужно освободить. Для это в функцию free передаем тот самый указатель, который мы запомнили. Груба говоря на каждый вызов malloc/calloc должен приходится вызов free.
Цитата Сообщение от Beg Посмотреть сообщение
насколько я знаю так
нет, все, что находится после оператора return не выполнится.
1
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
29.03.2013, 23:49  [ТС]
Цитата Сообщение от go Посмотреть сообщение
Systemes, когда функция malloc выделила память, то она вернула указатель на ее начало. Вы не должны его потерять. Когда вы перестаете нуждаться в этой памяти, то ее нужно освободить. Для это в функцию free передаем тот самый указатель, который мы запомнили. Груба говоря на каждый вызов malloc/calloc должен приходится вызов free.
Это я понимаю)) Вычитал из документации)) Тут чуть другое. Нужно и вернуть указатель params, и во free его передать, иначе память будет выделяться, но не будет освобождаться, т.е. получаю утечку. Вот мне и не понятно каким образом можно устранить утечку и не потерять данные params в данном случае...
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
29.03.2013, 23:57
"и вернуть и засунуть во free" - задача никак не решается.
можно конечно освободить память и вернуть указатель на нее, но пользоваться ей нельзя будет.
схема простая:
тот кто вызывает функцию php_array_to_c_array получает от нее указатель на память и он отвечает за вызов какой-то функции, которая приведет у удалению выделенной памяти. если он это сделать не в состоянии - то задачка не решается.
1
go
Эксперт С++
3646 / 1378 / 243
Регистрация: 16.04.2009
Сообщений: 4,526
30.03.2013, 00:02
Systemes, а. Понял. Вариантов масса.
1. Создать класс. И освобождать память в деструкторе.
2. Возложить обязанность на освобождение памяти на подпрограмму, которая вызывает вашу функцию php_array_to_c_array.
0
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
30.03.2013, 00:11  [ТС]
Да есть указатель)) Я не подумал что через указатель можно освободить память, по этому не копал в эту сторону(( Но даже в этом случае что-то постепенно съедает память
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
typedef struct _efree_node_t {
  void *ptr;
  struct _efree_node_t *next;
} efree_node_t;
 
typedef struct _efree_list_t {
  efree_node_t *head, *tail;
} efree_list_t;
 
efree_list_t efree_list_on_flush_t;
 
void add_efree_list_on_flush(void *ptr) {  // сюда params отправляется из php_array_to_c_array
  efree_node_t *node = (efree_node_t *)malloc(sizeof(efree_node_t));
  node->ptr = ptr;
  node->next = NULL;
  if (efree_list_on_flush_t.head == NULL) {
    efree_list_on_flush_t.head = node;
    efree_list_on_flush_t.tail = node;
  } else {
    efree_list_on_flush_t.tail->next = node;
    efree_list_on_flush_t.tail = node;
  }
}
void free_efree_list_on_flush() {  // тут освобождается память
  efree_node_t *node, *next;
  node = efree_list_on_flush_t.head;
  while (node) {
    next = node->next;
    free(node->ptr);
    node = next;
  }
  efree_list_on_flush_t.head = NULL;
  efree_list_on_flush_t.tail = NULL;
}
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.03.2013, 00:11
Цитата Сообщение от Systemes Посмотреть сообщение
суть вот в чем, функция ест память!
Суть не в этом. Память в функции выделилась, копия указателя на неё вернулась из функции. Нужно дальше в коде смотреть, что происходит с этим указателем. Если значение его не сохранить, то будет утечка (указатель локальный). Когда эта память перестанет быть нужной, или перед очередным вызовом функции, нужно эту память освободить. Ещё вариант: объявить этот указатель глобально, в начале функции проверять, есть ли под ним память, если есть освобождать, и только потом выделять новую.
1
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
30.03.2013, 14:34  [ТС]
Ну в общем я понял куда копать)

Добавлено через 14 часов 13 минут
мне так и не удалось решить проблему с утечкой памяти
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
typedef struct _efree_node_t {
  void *ptr;
  struct _efree_node_t *next;
} efree_node_t;
 
typedef struct _efree_list_t {
  efree_node_t *head, *tail;
} efree_list_t;
 
efree_list_t efree_list_on_flush_t;
 
void add_efree_list_on_flush(void *ptr) {  // сюда params отправляется из php_array_to_c_array
  efree_node_t *node = (efree_node_t *)malloc(sizeof(efree_node_t));
  node->ptr = ptr;
  node->next = NULL;
  if (efree_list_on_flush_t.head == NULL) {
    efree_list_on_flush_t.head = node;
    efree_list_on_flush_t.tail = node;
  } else {
    efree_list_on_flush_t.tail->next = node;
    efree_list_on_flush_t.tail = node;
  }
}
void free_efree_list_on_flush() {  // тут освобождается память
  efree_node_t *node, *next;
  node = efree_list_on_flush_t.head;
  while (node) {
    next = node->next;
    free(node->ptr);
    node = next;
  }
  efree_list_on_flush_t.head = NULL;
  efree_list_on_flush_t.tail = NULL;
}
если меняю

C++
1
2
3
void add_efree_list_on_flush(void *ptr) {  // сюда params отправляется из php_array_to_c_array
  free(ptr);
}
утечка исчезает, следовательно проблема в функции free_efree_list_on_flush которая отвечает за освобождение памяти. В общем я реально запутался(
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.03.2013, 17:49
Утечка памяти - это когда указатели на выделенную память теряются. У вас может этого и нет. Может просто большой расход памяти, но это другое. Если я правильно понимаю, у вас связанный список, и на каждый узел выделяется память, а освобождение памяти происхоит, когда список удаляется. Это не утечка, код такой. Как с этим бороться и можно ли, нужно подумать...
0
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
30.03.2013, 20:24  [ТС]
Да вы правильно поняли))И к сожалению пока не могу найти ответа как справиться с данной проблемой...
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
30.03.2013, 22:18
Цель кода в чём?

Добавлено через 1 минуту
Если просто создать массив, то массив будет занимать память, и с этим ничего не сделать. Памяти не хватает при работе программы?

Добавлено через 1 минуту
Памяти расходуется больше, чем размер массива?
0
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
31.03.2013, 11:33  [ТС]
Память расходуется в зависимости от размера поступившего массива. Причем чем больше массив, тем меньше расходуется памяти. Но есть порог, при котором память снова начинает расходоваться.

Память расходуется постепенно. При 65 вызовах ф-ии в сек-у где-то 0.22 мб в секунду, при учете что в массиве передается один парамет равный 0.

По идее к add_efree_list_on_flush будет обращается сразу несколько разных ф-й, и потом идет очищение памяти:

add_efree_list_on_flush
add_efree_list_on_flush
add_efree_list_on_flush

free_efree_list_on_flush

структура будет такая...
Ссылка на массив поступая в add_efree_list_on_flush отправляется еще и в основную ф-ю.
free_efree_list_on_flush вызывается когда с массивами произойдут все операции
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
31.03.2013, 14:12
Интересно, а какое это отношение тема имеет к С++? Чистый С же. Применимо к ++ следовало бы использовать какой-нибудь из smart-pointer'ов.
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
31.03.2013, 20:52
???
Цитата Сообщение от alsav22 Посмотреть сообщение
Цель кода в чём?
Цитата Сообщение от alsav22 Посмотреть сообщение
Памяти не хватает при работе программы?
Добавлено через 6 минут
Чтобы попытаться разобраться с расходом памяти, того кода, который вы показали, недостаточно.
0
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
31.03.2013, 21:46  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//-- объявление констант
void *php_array_to_c_array(zval *param,int type,int size,int *array_size);
#define php_array_to_string_array(z) (char **)php_array_to_c_array(z,TO_C_STRING,sizeof(char *),NULL)
#define php_array_to_byte_array(z) (char *)php_array_to_c_array(z,TO_C_BYTE,sizeof(char),NULL)
#define php_array_to_ubyte_array(z) (unsigned char*)php_array_to_c_array(z,TO_C_UBYTE,sizeof(unsigned char),NULL)
#define php_array_to_long_array(z) (long *)php_array_to_c_array(z,TO_C_LONG,sizeof(long),NULL)
#define php_array_to_double_array(z) (double *)php_array_to_c_array(z,TO_C_DOUBLE,sizeof(double),NULL)
#define php_array_to_int_array(z) (int *)php_array_to_c_array(z,TO_C_INT,sizeof(int),NULL)
#define php_array_to_float_array(z) (float *)php_array_to_c_array(z,TO_C_FLOAT,sizeof(float),NULL)
#define php_array_to_uchar_array(z) (unsigned char *)php_array_to_c_array(z,TO_C_UCHAR,sizeof(unsigned char),NULL)
#define php_array_to_schar_array(z) (signed char *)php_array_to_c_array(z,TO_C_SCHAR,sizeof(signed char),NULL)
#define php_array_to_ushort_array(z) (unsigned short *)php_array_to_c_array(z,TO_C_USHORT,sizeof(unsigned short),NULL)
#define php_array_to_short_array(z) (short *)php_array_to_c_array(z,TO_C_SHORT,sizeof(short),NULL)
#define php_array_to_uint_array(z) (unsigned int *)php_array_to_c_array(z,TO_C_UINT,sizeof(unsigned int),NULL)
 
// -- объявление zend функции pointer
ZEND_FUNCTION(pointer)
{
zval *type, *pointer;
void *v_pointer = NULL;
TWO_PARAM(type, pointer);
convert_to_array(pointer);
switch(Z_LVAL_P(type))
{
case T_SHORT:
v_pointer = php_array_to_short_array(pointer);
break;
case T_INT:
v_pointer = php_array_to_int_array(pointer);
break;
case T_FLOAT:
v_pointer = php_array_to_float_array(pointer);
break;
case T_DOUBLE:
v_pointer = php_array_to_double_array(pointer);
break;
}
Pointer((int)Z_LVAL_P(type),(void*)v_pointer);
add_efree_list_on_flush(v_pointer);
}
 
//-- ф-я обработки
ZEND_FUNCTION(flush)
{
ZERO_PARAM();
Flush();
free_efree_list_on_flush();
}
Это оставшийся код, который участвует во всей схеме. Но основные ф-ии pointer и flush память точно не расхдуют. Т.к. закоментировав эти ф-ии получаю ту же "утечку", или передавая массив написанный в ручную, без ф-ии конвертации (т.е. не используя php_array_to_c_array и free_efree_list_on_flush) память не расходуется)
0
5500 / 4895 / 831
Регистрация: 04.06.2011
Сообщений: 13,587
31.03.2013, 22:14
И как это проверять?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
31.03.2013, 22:14
Помогаю со студенческими работами здесь

Работа с памятью через malloc,realloc и free
Вот начал работать с памятью в c++ и появилось несколько вопросов. 1 - r = (int *)malloc((1)*sizeof(int)); как я понимаю, эта запись...

И снова динамическая память, malloc и free в конструкторе и деструкторе
Короче есть, класс, который например хранит строку, я его храню в структуре, после я выдиляю динамическу память пот эту структуру и копирую...

Резервирование памяти/освобождение памяти для трехмерного массива
Необходимо создать трехмерный массив (A), в котором элементы вдоль направления Z выли бы выровнены по 16 байт. Есть две проблемы: ...

В чем преимущества new и delete и могут ли они действительно заменить функции calloc, malloc, free, realloc?
Язык программирования C поддерживает функции динамического управления пямятью: calloc, malloc, free, realloc - которые неподдерживают...

Выделение памяти malloc
не работает пример из лекции , там пример на доске такой написан - #include <stdlib.h> int main() { int...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru