Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.63
Systemes
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
#1

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

29.03.2013, 22:02. Просмотров 2354. Ответов 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
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
29.03.2013, 22:02
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Освобождение памяти malloc free (C++):

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

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

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

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

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

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

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Beg
0 / 0 / 0
Регистрация: 29.03.2013
Сообщений: 17
29.03.2013, 23:20 #2
C++
1
2
3
return (void *)params;
free(params);
}
насколько я знаю так
0
go
Эксперт C++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
29.03.2013, 23:28 #3
Systemes, когда функция malloc выделила память, то она вернула указатель на ее начало. Вы не должны его потерять. Когда вы перестаете нуждаться в этой памяти, то ее нужно освободить. Для это в функцию free передаем тот самый указатель, который мы запомнили. Груба говоря на каждый вызов malloc/calloc должен приходится вызов free.
Цитата Сообщение от Beg Посмотреть сообщение
насколько я знаю так
нет, все, что находится после оператора return не выполнится.
1
Systemes
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
29.03.2013, 23:49  [ТС] #4
Цитата Сообщение от go Посмотреть сообщение
Systemes, когда функция malloc выделила память, то она вернула указатель на ее начало. Вы не должны его потерять. Когда вы перестаете нуждаться в этой памяти, то ее нужно освободить. Для это в функцию free передаем тот самый указатель, который мы запомнили. Груба говоря на каждый вызов malloc/calloc должен приходится вызов free.
Это я понимаю)) Вычитал из документации)) Тут чуть другое. Нужно и вернуть указатель params, и во free его передать, иначе память будет выделяться, но не будет освобождаться, т.е. получаю утечку. Вот мне и не понятно каким образом можно устранить утечку и не потерять данные params в данном случае...
0
DU
1483 / 1059 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
29.03.2013, 23:57 #5
"и вернуть и засунуть во free" - задача никак не решается.
можно конечно освободить память и вернуть указатель на нее, но пользоваться ей нельзя будет.
схема простая:
тот кто вызывает функцию php_array_to_c_array получает от нее указатель на память и он отвечает за вызов какой-то функции, которая приведет у удалению выделенной памяти. если он это сделать не в состоянии - то задачка не решается.
1
go
Эксперт C++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
30.03.2013, 00:02 #6
Systemes, а. Понял. Вариантов масса.
1. Создать класс. И освобождать память в деструкторе.
2. Возложить обязанность на освобождение памяти на подпрограмму, которая вызывает вашу функцию php_array_to_c_array.
0
Systemes
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
30.03.2013, 00:11  [ТС] #7
Да есть указатель)) Я не подумал что через указатель можно освободить память, по этому не копал в эту сторону(( Но даже в этом случае что-то постепенно съедает память
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
alsav22
5420 / 4816 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.03.2013, 00:11 #8
Цитата Сообщение от Systemes Посмотреть сообщение
суть вот в чем, функция ест память!
Суть не в этом. Память в функции выделилась, копия указателя на неё вернулась из функции. Нужно дальше в коде смотреть, что происходит с этим указателем. Если значение его не сохранить, то будет утечка (указатель локальный). Когда эта память перестанет быть нужной, или перед очередным вызовом функции, нужно эту память освободить. Ещё вариант: объявить этот указатель глобально, в начале функции проверять, есть ли под ним память, если есть освобождать, и только потом выделять новую.
1
Systemes
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
30.03.2013, 14:34  [ТС] #9
Ну в общем я понял куда копать)

Добавлено через 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
alsav22
5420 / 4816 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.03.2013, 17:49 #10
Утечка памяти - это когда указатели на выделенную память теряются. У вас может этого и нет. Может просто большой расход памяти, но это другое. Если я правильно понимаю, у вас связанный список, и на каждый узел выделяется память, а освобождение памяти происхоит, когда список удаляется. Это не утечка, код такой. Как с этим бороться и можно ли, нужно подумать...
0
Systemes
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 11
30.03.2013, 20:24  [ТС] #11
Да вы правильно поняли))И к сожалению пока не могу найти ответа как справиться с данной проблемой...
0
alsav22
5420 / 4816 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
30.03.2013, 22:18 #12
Цель кода в чём?

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

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

Память расходуется постепенно. При 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
Tulosba
:)
Эксперт С++
4396 / 3239 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
31.03.2013, 14:12 #14
Интересно, а какое это отношение тема имеет к С++? Чистый С же. Применимо к ++ следовало бы использовать какой-нибудь из smart-pointer'ов.
0
alsav22
5420 / 4816 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
31.03.2013, 20:52 #15
???
Цитата Сообщение от alsav22 Посмотреть сообщение
Цель кода в чём?
Цитата Сообщение от alsav22 Посмотреть сообщение
Памяти не хватает при работе программы?
Добавлено через 6 минут
Чтобы попытаться разобраться с расходом памяти, того кода, который вы показали, недостаточно.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.03.2013, 20:52
Привет! Вот еще темы с ответами:

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

освобождение памяти - C++
Помогите найти ошибку, программа вилиться когда освобождаю память! Здесь выделения памяти double **CreateArray() { double...

Освобождение памяти - C++
Есть класс дроби с перегруженным оператором приведения к char * Fraction::operator char*() { char num=""; char denom=""; ...

Освобождение памяти - C++
Есть многопоточное приложение. Создается глобальная структура: Пример из msdn. typedef struct _MyData { int val1; ...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
31.03.2013, 20:52
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru