Выгрузить динамическую библиотеку нужно два вызова dlclose ()? - PullRequest
9 голосов
/ 09 января 2012

У меня есть динамическая библиотека, которую я загружаю с помощью dlopen(), а затем выгружаю с помощью dlclose();

Если я не включаю какой-либо объективный код c, то dlopen() нужен один dlclose() вызов, что является ожидаемым поведением. Но когда я включаю любой целевой код c в цель, у меня возникает проблема, что мне нужно сделать два dlclose() вызова загруженной библиотеки, чтобы выгрузить.

Это ожидаемое поведение? Как я могу это исправить?

1 Ответ

29 голосов
/ 09 января 2012

Я понимаю, что вы используете dlopen, а не CFBundle или NSBundle. Тем не менее, руководство по программированию * Загрузка кода говорит об этом:

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

и это:

Из-за ограничения в среде выполнения Objective C NSBundle не может выгружать исполняемый код.

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

Я искал исходный код среды выполнения Objective C и нашел this :

// dylibs are not allowed to unload
// ...except those with image_info and nothing else (5359412)
if (result->mhdr->filetype == MH_DYLIB  &&  _hasObjcContents(result)) {
    dlopen(result->os.dl_info.dli_fname, RTLD_NOLOAD);
}

Так что да, среда выполнения Objective C вызывает dlopen для вашей библиотеки специально, чтобы предотвратить ее выгрузку. Если вы обманываете и дважды звоните dlclose, вы должны ожидать, что произойдут плохие вещи.

...