2012-05-15 4 views
6

читать об этом here.Как выполнить подсчет ссылок в C?

Мне нужно реализовать вариант такого интерфейса, скажем, нам предоставлено большое пространство памяти для управления, должны быть функции getmem (size) и free (указатель на блок), которые должны быть уверены, что они свободны (указатель на блокировку) может фактически освободить память тогда и только тогда, когда все процессы, использующие этот блок, будут выполнены с использованием этого.

Что я думал о том, чтобы определить структуру Collectable как указатель на блок, его размер и процесс, используя его счет. то всякий раз, когда процесс с использованием экземпляра структуры Collectable в первый раз ему приходится явно увеличивать счетчик, и всякий раз, когда процесс free(), он уменьшается.

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

Я ищу способов подойти к этой проблеме на некоторое время, так что другие подходы и идеи были бы больш ...

EDIT: выше подход не удовлетворяет меня не только потому, что Безразлично 't выглядят хорошо, но главным образом потому, что я не могу предположить, что код исполняемого процесса будет заботиться об обновлении моего счета. Мне нужен способ убедиться, что это сделано без изменения кода процесса ...

+0

Это не проблема для C. Именно поэтому были созданы другие языки на основе C, например: Objective-C, C++, C# и т. Д. –

+0

Я знаю, но это то, что я должен сделать для домашней работы ... так ... –

+4

Тот факт, что каждая копия указателя должна быть инструментальной, не является «проблемой с этим подходом»: это фундаментальная проблема подсчета ссылок. –

ответ

3

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

Поскольку C не имеет возможности переопределить оператор присваивания (для подсчета новой ссылки), в основном вы остаетесь с ограниченным количеством параметров. Единственный, который может переопределить назначение, - это macrodef, так как он имеет возможность переписать присваивание во что-то, что увеличивает приращение значения счетчика ссылок.

Так что вам нужно «расширить» макрос, который выглядит как

a = b; 

в

if (b is a pointer) { // this might be optional, if lookupReference does this work 
    struct ref_record* ref_r = lookupReference(b); 
    if (ref_r) { 
    ref_r->count++; 
} else { 
    // error 
    } 
} 
a = b; 

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

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

Другие варианты (возможно, более разумные, возможно, нет) - отслеживать все значения адресов, назначенные malloc, а затем сканировать стек программы и кучу для сопоставления адресов. Если вы согласитесь, вы найдете , возможно, нашли действительный указатель, или вы могли бы найти строку с кодировкой удачи; однако, если вы не согласны, вы, безусловно, можете освободить адрес; при условии, что они не сохраняют адрес + смещение, рассчитанное с исходного адреса. (возможно, вы можете macrodef обнаружить такие смещения и добавить смещение в виде нескольких адресов при сканировании для того же блока)

В конце концов, не будет надежного решения без создания системы ссылок, где вы передаете обратные ссылки (притворяются адреса); скрывая реальные адреса. Нижняя сторона такого решения заключается в том, что вы должны использовать интерфейс библиотеки каждый раз, когда вы хотите иметь дело с адресом. Это включает в себя «следующий» элемент в массиве и т. Д. Не очень C-like, но довольно хорошее приближение к тому, что делает Java со своими ссылками.

+0

хорошо вы говорите 2 противоположных предмета, один из них заключается в том, что нет возможности переопределить назначение второго, что это можно сделать с помощью макродефа ... так? –

+0

Они не совсем противоположные утверждения. Overriding - это технический термин, означающий «переопределить стандартные функции с нестандартной реализацией», в то время как macrodef - это подсистема расширения текста, которая не будет повторно выполнять назначение, но вы можете вырезать и вставлять код, если вы видите «соответствие». Тогда вам будет нужно узнать, можете ли вы сначала написать высококачественное совпадение, а затем «вырезать и вставить» в код «увеличить количество ссылок». Это возможно в теории, но macrodef настолько ограничен языком, что на самом деле это невозможно из-за ограничений макродефа. –

+1

Подсчет ссылок в хэш-таблице не так, как кто-либо это делает. Правильный способ - включить счет в структуру/буфер. – asveikau

0

Я не думаю, что вы можете сделать это автоматически без переопределяемых деструкторов/конструкторов. Вы можете посмотреть на подсчете рефа HDF5 но те требуют явных вызовов в C:

http://www.hdfgroup.org/HDF5/doc/RM/RM_H5I.html

+0

Но почему точно вы рекомендуете смотреть HDF5? – hmijail

1

Semi-серьезный ответ

#include "Python.h" 

Python имеет большой менеджер подсчета памяти ссылки. Если бы мне пришлось делать это по-настоящему в производственном коде, а не в домашнем задании, я бы подумал о внедрении системы объектов python в мою программу на C, которая затем сделала бы мою программу на языке сценариев сценариями на языке python. См. the Python C API documentation, если вы заинтересованы!

+0

, как я сказал, другие языки не имеют отношения к нашему обсуждению ... –

+8

Этот ответ относится к API Python C, который является интересным ресурсом в отношении этого вопроса, поскольку упомянутый API включает ссылки, подсчитанные C "объектами". – olovb

2

Такая система в C требует определенной дисциплины со стороны программиста, но ...

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

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

Таким образом, вам необходимо определить, в каких ситуациях объекты должны передаваться или совместно использоваться новыми владельцами и переносить соответствующие ситуации в макросы/функции, которые добавляют или удаляют принадлежащие им объекты в списки объектов объектов, на которые ссылаются объекты (и настраивают счетчик ссылок соответственно).

Наконец-то вам нужно как-то разобраться с круговыми ссылками, проверив объекты, которые больше не доступны из объектов/указателей в стеке. Это можно сделать с помощью некоторого механизма сбора мусора и разметки мусора.

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