2009-04-09 6 views
4

У меня есть программа на C++, которая сравнивает различные алгоритмы на входных массивах разной длины. Это выглядит более или менее, как это:Сбор мусора/сжатие с malloc()

# (1) 
for k in range(4..20): 
    # (2) 
    input = generate 2**k random points 
    for variant in variants: 
    benchmark the following call 
    run variant on input array 
    # (3) 

Можно ли сбросить все управление кучи в (2) в состояние, было в (1)? Вся память, выделенная в куче, которая была распределена во время программы, гарантируется освобождением в (3).

Я использую g ++ 4.3 для Linux.

Редактировать: Я понимаю, что в C/C++ нет реальной сборки мусора. Я хочу заставить выделение памяти присоединиться к смежным пустым кускам памяти, которые он имеет в своем свободном списке в (2).

+0

C/C++ даже не гарантирует, что существует свободный список. Язык не заботится о том, как работает управление памятью. Это все зависит от ОС. Таким образом, единственный способ обеспечить аналогичное состояние в # 2 - это, как предложил jpalecek и RnR, начать новый процесс. – jalf

+0

Я надеялся, что система времени исполнения gcc имеет функцию, которую я мог бы как-то вызвать. Это не должно быть переносимым. – Manuel

+0

Manuel - у вас есть два решения: jpalecek, который может быть проще и быстрее реализовать, а мой - портативный и дает 100% гарантию относительно результатов (с вилкой успешные процессы наследуют другую среду - та, в которой n-1 другие процессы были раздвоены), используйте их :) – RnR

ответ

6

Если вы хотите, чтобы тестовые прогоны запускались в одинаковых состояниях кучи, вы можете запускать их в своих собственных процессах, созданных fork().

+0

Я пришел с вопросом только об этом сейчас - используя fork, следующий процесс наследует другое состояние, а затем предыдущее - подробно среда, в которой n-1 вилки уже выполнены - мое предложение было первым и имеет гарантию точно такие же условия для всех процессов;) – RnR

+0

Если вы правильно его реализуете, единственное различие между состоянием разветвленных процессов будет разными значениями в массиве дочерних PID. Никакой разницы в куче. В отличие от подхода сценария оболочки, он имеет возможность беспрепятственно передавать произвольно сложные структуры детям. – jpalecek

+0

Откуда вы знаете, что вызовет вилка в кучу? Не считаете ли вы, что память должна быть выделена/выпущена при выполнении новых процессов? Например, чтобы скопировать дескрипторы файлов и т. Д.? Это проще - как я добавил, но гораздо менее «гарантировано», чтобы быть идентичным - по крайней мере, имхо. – RnR

1

Невозможно сделать это с помощью стандартного C++, не выполняя собственные версии новых &, удаляя их собственным управлением кучей. Альтернативой было бы не использование массивов, а использование std :: vector вместо этого - вы можете использовать собственный распределитель для управления кучей.

+0

Поскольку я использую библиотеку для некоторых вариантов, которые используют свои собственные контейнеры, я не могу этого сделать. – Manuel

0

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

+0

Насколько я понимаю, malloc() уже отделил некоторую память на куски, которые я использовал в своей программе. Эти куски должны быть в свободном списке, но если у меня есть два куска, каждый из которых имеет размер 1M, их нужно объединить, если я хочу повторно использовать эту часть памяти, когда мне нужно 2M. – Manuel

+0

Возможно, вы хотите использовать realloc? Вы не можете присоединиться к двум различным блокам памяти, потому что они должны быть последовательно в памяти. –

+0

@ Manuel: Нет, malloc не отделяет память на кусок. И после этого они не будут помещены в свободный список, и они не будут иметь размер 1M. Ни один из них не указан языком. Это зависит от ОС, чтобы делать все это, и это не имеет ничего общего с C/C++ – jalf

1

Что вы имеете в виду? В C нет сборки мусора и, конечно же, никакого уплотнения.

Чтобы «сбросить состояние кучи», вы должны вызвать free() для каждого вызова malloc(). И, как я понимаю ваш код, вы делаете это уже.

Уплотнение в значительной степени невозможно. В отличие от языков более высокого уровня, таких как Java или C#, вы не можете изменить адрес объекта, потому что любые указатели на него будут признаны недействительными.

+0

Я понимаю проблему с указателями. Я хочу заставить систему выделения памяти присоединиться к смежным пустым ячейкам памяти. – Manuel

+0

Есть еще один способ кошки кошки - пожалуйста, см. Мой ответ :) (Я вижу, что у jpalecek есть аналогичная идея) – RnR

+0

@RnR: heh, true. @Manuel, то, что вы просите, не имеет смысла. ОС будет делать все, что угодно, все время. На разумной ОС он * будет * объединять смежные куски, как только они станут доступны, и вам не нужно ничего делать. Но если это не так, вы ничего не можете с этим сделать – jalf

3

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

+0

Хех, +1 Это единственный разумный способ решить вопрос. – jalf

0

Их несколько частей кода сбора мусора из их. Посмотрите на perl/python/lua/ruby ​​/ mono/parrot/boehm/pike/slate/self/io и т. Д. И т. Д. Также посмотрите на alloca() и динамические массивы. Также рассмотрите возможность использования структур для реализации вашего собственного деструктора или использования атрибутов gcc для бесплатного вызова при выходе из функции.

Смежные вопросы