C & Lua предотвращает плохой доступ или двойной бесплатный - PullRequest
3 голосов
/ 12 июля 2011

Я успешно интегрировал Lua в свое приложение C, предоставляя пользователям доступ к сценариям.Теперь моя проблема: как я могу предотвратить нарушения двойного свободного или неправильного доступа?

Я уже реализую функции Init и Free для каждой структуры, например:

  • structaInit
  • structaFree

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

Однако пользователивсегда мог сделать что-то подобное в Lua:

a = structaInit();

b = structbInit();

structbSetA( b, a ); -- This add ++a.reference

a.reference = 0; 

a = structaFree( a ); -- If a->reference == 0 then I free

-- Then struct b->a is still a valid pointer but that have been free.

Могу ли я в любом случае предотвратить это?

Ответы [ 2 ]

10 голосов
/ 12 июля 2011

Проблема связана с владением.Давайте возьмем ваши сценарии Lua:

a = structaInit();
b = structbInit();

Это создает объекты C, которые Lua теперь владеет .Lua решит, когда освободить память для этих объектов.

Так что же с этим?

structbSetA( b, a ); -- This add ++a.reference

Прежде всего, structbSetA должен быть членом b черезметатабельный (так становится b:setA(a)).Но что более важно, кому принадлежит a?

Луа.Потому что он должен владеть А;Lua не может полностью отказаться от владения объектом, который все еще находится в памяти Lua.Это означает, что ваш внутренний счетчик ссылок в конечном итоге не имеет смысла;единственное, что имеет значение, это Lua.

Если вы намереваетесь сохранить значение a в b, так что b может ссылаться на a, пока b еще жив,тогда вам нужно создать эти отношения с помощью Lua методов.Вы не можете просто прикрепить указатель C к a в b и ожидать, что все будет хорошо.

Самый простой способ сделать это - создать для каждого объекта, который вы создаете, таблицу вРеестр Lua, в котором хранится объект Lua для любых ссылок.Когда объект уничтожен, вы заходите в реестр Lua и удаляете из него эту таблицу, что приводит к уничтожению любых ссылочных объектов Lua.Очевидно, вам нужно будет изменить это значение, когда оно будет изменено последующими вызовами на structbSetA.


Кроме того, почему вы выставляете это Lua:

a.reference = 0;

Этоужасный API.Код Lua никогда не должен иметь дело со счетчиком ссылок.Вы также никогда не должны предоставлять явный «бесплатный» метод Lua, если только вам не нужно, чтобы Lua высвободил какой-либо ресурс сразу после его использования.И это only должно быть необходимо для ресурсов типа OS, таких как дескрипторы FILE и тому подобное.Для обычного объекта позвольте сборщику мусора выполнить свою работу.

Не открывайте C-isms для кода Lua.Пусть код Lua будет выглядеть как код Lua.

1 голос
/ 12 июля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...