C Программирование: malloc и свободный в цикле

Я только что начал с C, и имейте очень мало знания о проблемах производительности с malloc() и free(). Мой вопрос - это: если я должен был звонить malloc() сопровождаемый free() внутри a while цикл, что циклы для, скажем, 20 повторений, был бы он работать медленнее по сравнению с вызовом free() вне цикла?

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

6
задан Karl Richter 17 February 2018 в 00:06
поделиться

8 ответов

Определенно медленнее. (Но помните, что вам нужно сбалансировать количество malloc и free , иначе вы получите утечку памяти.)

Если длина меняется, вы можете использовать realloc ], чтобы увеличить размер буфера.

void* v = malloc(1024);
size_t bufsize = 1024;

while(cond) {
   size_t reqbufsize = get_length();
   if (reqbufsize > bufsize) {
      bufsize = reqbufsize * 2;
      v = realloc(v, bufsize);
   }
   // you may shrink it also.

   do_something_with_buffer(v);
}

free(v);
15
ответ дан 8 December 2019 в 02:40
поделиться

Это зависит от реализации malloc и бесплатно.

Лучший способ ответить на ваш вопрос - это построить эталон...

0
ответ дан 8 December 2019 в 02:40
поделиться

It зависит от того, для чего вам нужен буфер.

Вам действительно нужно очищать его после каждой итерации, или, может быть, символа \ 0 в конце будет достаточно, чтобы отметить конец строки? В конце концов, это то, что используют различные вызовы библиотеки str .

Если вам действительно нужно очистить его, вы можете использовать bzero () . Конечно, выделение и освобождение на каждой итерации - это пустая трата ресурсов, поскольку вы можете с удовольствием повторно использовать буфер.

Другая проблема могла бы возникнуть, если бы вы распараллелили цикл for, т.е. если бы его использовали несколько параллельных потоков.

Простой пример из реальной жизни: использование ведра для переноски воды. Предположим, вам нужно совершить несколько поездок с этим ведром: имеет ли смысл поднять его, использовать, положить, снова поднять, использовать и т. Д.? Вы можете повторно использовать ведро столько раз, сколько сможете. Если, с другой стороны, ведро необходимо использовать вам и большему количеству людей, либо вы организуете доступ к нему, либо вам нужно больше корзин.

Последнее предложение: не беспокойтесь о выступлениях . Говорят, что ранняя оптимизация - это корень всех зол, и вы скоро поймете, почему.

Во-первых, разберитесь в проблеме: напишите код, который можно выбросить. Экспериментируйте. Во-вторых, проверьте это.Убедитесь, что он делает то, что вам нужно. В-третьих, оптимизируйте его. Запустите цикл десять тысяч раз и измерьте, сколько времени это займет. Затем переместите malloc наружу и снова измерьте (используйте команду оболочки time в UNIX). В-четвертых, перепишите его, потому что ваш первый эксперимент, скорее всего, будет состоять из множества исправлений кода, который не работает.

Промыть, повторить.

ps: развлекайтесь пока что. Это должно быть интересно, а не расстраивать.

2
ответ дан 8 December 2019 в 02:40
поделиться

Для 20 итераций вам не стоит беспокоиться о производительности malloc/free.

Даже при значительно большей производительности (на пару порядков) не стоит начинать думать об оптимизации, пока вы не профилируете код и не поймете, что именно работает медленно.

Наконец, если вы собираетесь освободить буфер, нет необходимости сначала очищать его. Даже если вы перенесете malloc/free за пределы цикла (используя максимальный буфер, как предложил Джастин), вам не нужно явно очищать буфер.

6
ответ дан 8 December 2019 в 02:40
поделиться

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

3
ответ дан 8 December 2019 в 02:40
поделиться

Вообще все, что можно переместить за пределы цикла, должно быть перемещено. Зачем повторять одно и то же действие, если можно сделать это один раз?

Джастин Этье прав: выделите буфер, в который удобно поместится самая большая строка, и используйте его повторно.

1
ответ дан 8 December 2019 в 02:40
поделиться

Вы не можете вызвать free за пределами цикла, если вы вызываете malloc внутри:

char * buffer;
for (int i = 0; i < num_files; i++) {
    buffer = malloc(proper_length(i));
    // do some things with buffer
}
free(buffer);

Вы будете malloc'ed num_files раз, но только один раз - вы утекли память из всех, кроме последний!

Есть два основных варианта - malloc перед циклом (или просто использовать массив), если вы знаете размер, который будет работать для всего, или использовать realloc:

char * buffer = NULL;
for (int i = 0; i < num_files; i++) {
    buffer = realloc(proper_length(i));
    // do some things with buffer
}
free(buffer);
7
ответ дан 8 December 2019 в 02:40
поделиться

Улучшить обработку. Имейте некоторый псевдокод:

#define BLOCK_SIZE 1024 // or about the bigger size of your strings.

char *buffer = (char *) malloc(BLOCK_SIZE) 

for(int i=0; i<20; i++)
{
   while (more bytes left to read)
   {
    read full string or BLOCK_SIZE bytes at max // most calls work this way
    proces bytes in buffer
   }
}

free(buffer);
0
ответ дан 8 December 2019 в 02:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: