Шаблоны для освобождения памяти в C?

Я получил этот диктат:

task_formatted.append(str(item['entity']))

Я преобразую его в str, затем добавляю в список, чтобы я мог легко передать его в свой шаблон

blockquote >

Этот код не делает то, что вы думаете.

>>> entity = {'type': 'Asset', 'id': 1404, 'name': 'Test-Asset commé'}
>>> str(entity)
"{'type': 'Asset', 'id': 1404, 'name': 'Test-Asset comm\\xc3\\xa9'}"

Когда вы вызываете str для словаря (или списка), вы не получаете результат вызова str для каждого ключа и значений словаря: вы получаете repr [1118 ] каждого ключа и значения. В этом случае это означает, что 'Test-Asset commé' был преобразован в 'Test-Asset comm \ xc3 \ xa9' способом, который трудно изменить.

>>> str(entity).decode('utf-8')  # <- this doesn't work.
u"{'type': 'Asset', 'id': 1404, 'name': 'Test-Asset comm\\xc3\\xa9'}"

Если вы хотите визуализировать свои словари в шаблоне, используя только {{ item }}, вы можете использовать модуль json для их сериализации вместо str. Обратите внимание, что вам нужно преобразовать json (который имеет тип str) в экземпляр unicode , чтобы избежать UnicodeDecodeError при рендеринге шаблона.

>>> import json
>>> template = jinja2.Template(u"""{{item}}""")
>>> j = json.dumps(d, ensure_ascii=False)
>>> uj = unicode(j, 'utf-8')
>>> print template.render(item=uj)
{"type": "Asset", "id": 1404, "name": "Test-Asset commé"}

Некоторые общие замечания / выводы:

  • Не используйте str (или unicode) для сериализации контейнеров, таких как словари или списки; используйте инструменты, такие как json или pickle .
  • Убедитесь, что любые строковые литералы, которые вы передаете jinja2, являются экземплярами unicode, а не str
  • При использовании Python2, если есть вероятность того, что ваш код будет обрабатывать не-ascii значения, всегда используйте unicode, никогда не используйте str.
  • [Тысяча сто тридцать одна]
5
задан Abignale 28 March 2009 в 03:23
поделиться

7 ответов

Рассмотрите обертки к malloc и использование их дисциплинированным способом. Отследите память, что Вы действительно выделяете (в связанном списке, возможно) и используете обертку для выхода для перечисления памяти для освобождения ее. Вы могли также назвать память с дополнительным параметром и членом Вашей структуры связанного списка. В приложениях, где выделенная память является высоко зависимым объема, Вы пропустите память, и это может быть хорошим методом вывести память и проанализировать ее.

ОБНОВЛЕНИЕ: Поточная обработка в Вашем приложении сделает это очень сложным. См., что другие ответы расценивают проблемы поточной обработки.

3
ответ дан 13 December 2019 в 05:42
поделиться

Совет Michael является разумным - если Вы выходите, Вы не должны волноваться об освобождении памяти, так как система исправит его так или иначе.

Одним исключением к этому являются сегменты общей памяти - по крайней мере, под Общей памятью System V. Те сегменты могут сохраниться дольше, чем программа, которая создает их.

Одна опция, не упомянутая до сих пор, состоит в том, чтобы использовать основанную на арене схему выделения памяти, созданную сверху стандарта malloc(). Если целое приложение использует единственную арену, Ваш код очистки может выпустить ту арену, и все освобождено сразу. (APR - Apache, который Портативное Время выполнения - обеспечивает функции пулов, которой я верю, подобен; David Hanson "C Интерфейсы и Реализации" обеспечивает основанную на арене систему выделения памяти; я записал тот, который Вы могли использовать, если бы Вы хотели.) Можно думать об этом как о сборке "мусора" "бедного человека".

Как общая дисциплина памяти, каждый раз, когда Вы выделяете память динамично, необходимо понять, какой код собирается выпустить ее и когда она может быть выпущена. Существует несколько стандартных шаблонов. Самое простое "выделяется в этой функции; выпущенный перед этой функцией возвраты". Это сохраняет память в основном под управлением (если Вы не выполняете слишком много повторений на цикле, который содержит выделение памяти), и определяет объем его так, чтобы это могло быть сделано доступным для текущей функции и функций, которые это вызывает. Очевидно, необходимо быть довольно уверены, что функции, которые Вы вызываете, не собираются запасаться (кэш) указателями на данные и попытку снова использовать их позже после того, как Вы выпустили и снова использовали память.

Следующий стандартный шаблон иллюстрируется fopen() и fclose(); существует функция, которая выделяет указатель на некоторую память, которая может использоваться кодом вызова и затем выпускаться, когда программа закончилась с ним. Однако это часто становится очень похожим на первый случай - это обычно - хорошая идея звонить fclose() в функции, которая звонила fopen() также.

Большинство остающихся 'шаблонов' является несколько специальным.

1
ответ дан 13 December 2019 в 05:42
поделиться

Очень просто почему бы не ссылка считала реализацию, поэтому когда Вы создаете объект и передаете его вокруг Вас, увеличивают и постепенно уменьшаются, ссылка считаемое число (не забудьте быть атомарными, если у Вас есть больше чем один поток).

Тот путь, когда объект больше не используется (нулевые ссылки) можно безопасно удалить его или автоматически удалить его в вызове декремента подсчета ссылок.

0
ответ дан 13 December 2019 в 05:42
поделиться

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

Ответ: это зависит. Существует много стратегий, которые можно использовать.

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

Эти изменения стратегии, например, если Вы разрабатываете во встроенной операционной системе где exit() не мог бы очистить все. Обычно то, что я вижу, - когда отдельные функции возвращаются из-за ошибки, они удостоверяются, что очистили что-либо, что они сами выделили. Вы не видели бы никого exit() вызовы после вызова, скажем, 10 функций. Каждая функция в свою очередь указала бы на ошибку, когда она возвращается, и каждая функция вымылась бы после себя. Оригинал main() функция (если Вы будете - это нельзя было бы назвать main()) обнаружил бы ошибку, очистил бы любую память, которую она выделила и принимает соответствующие меры.

Когда у Вас просто есть объемы в объемах, это не аэрокосмические исследования. То, где это становится трудным, - то, если у Вас есть несколько потоков выполнения и структур совместно используемых данных. Затем Вам, возможно, понадобились бы сборщик "мусора" или способ считать ссылки и освободить память, когда последний пользователь структуры сделан с нею. Например, при рассмотрении источника к сетевому стеку BSD Вы будете видеть, что он использует a refcnt значение (подсчета ссылок) в некоторых структурах, которые должны быть поддержаны в течение длительного промежутка времени и общих для различных пользователей. (Это в основном, что сборщики "мусора" делают, также.)

3
ответ дан 13 December 2019 в 05:42
поделиться

Можно создать простого диспетчера памяти для malloc'd памяти, которая совместно используется объемами/функциями.

Зарегистрируйте его, когда Вы malloc это, вычеркните из списка его при освобождении его. Имейте функцию, которая освобождает всю зарегистрированную память перед вызовом выхода.

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

1
ответ дан 13 December 2019 в 05:42
поделиться

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

3
ответ дан 13 December 2019 в 05:42
поделиться

Звучит как задача для сборщика мусора Боэма.

http://www.hpl.hp.com/personal/Hans_Boehm/gc/

Зависит от системы конечно, можете ли вы себе это позволить или должны ли его использовать.

0
ответ дан 13 December 2019 в 05:42
поделиться
Другие вопросы по тегам:

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