2014-11-26 5 views
0

В Ubuntu 14.04 у меня есть C++ API в качестве общей библиотеки, которую я открываю с помощью dlopen, а затем создаю указатели на функции с помощью dlsym. Одна из этих функций CloseAPI освобождает API из памяти. Синтаксис:Вызов общих библиотек без освобождения памяти

void* APIhandle = dlopen("Kinova.API.USBCommandLayerUbuntu.so", RTLD_NOW|RTLD_GLOBAL); 
int (*CloseAPI) = (int (*)()) dlsym(APIhandle,"CloseAPI"); 

Если я гарантировать, что во время моего кода, функция CloseAPI всегда вызывается перед main функция возвращает, то все, кажется, хорошо, и я могу запустить программу снова в следующий раз. Однако, если I Ctrl-C и прервать программу, прежде чем она успела позвонить CloseAPI, то в следующий раз, когда я запустил программу, я получаю обратную ошибку всякий раз, когда я вызываю любую из функций API. У меня нет документации о том, что это за ошибка, но моя интуиция заключается в том, что в предыдущем запуске программы есть некоторая блокировка в библиотеке. Единственное, что позволяет мне снова запустить программу, - это перезагрузить мою машину. Вход и выход не работает.

Итак, мои вопросы:

1) Если моя библиотека является общая библиотека, почему я получаю эту ошибку, когда я бы подумал, разделяемая библиотека может быть загружена более чем одной программы одновременно?

2) Как я могу решить эту проблему, если я буду ожидать, что Ctrl-C будет происходить часто, не имея возможности позвонить CloseAPI?

+0

Это не решение, но как насчет обработчика сигналов, который обрабатывает C-c (и т. П. SIGINT, не так ли?)? – keyser

+0

Как говорит @keyser, обработка сигналов через 'signal (2)' или 'sigaction (2)' и вызов 'CloseAPI' в обработчике будет способом. – msandiford

+1

Попробовали использовать ltrace. Этот инструмент отображает вызовы, которые пользовательское приложение делает для разделяемых библиотек. Он делает это, подключаясь к динамической системе загрузки, позволяя ему вставлять прокладки, которые отображают параметры, которые приложения используют при совершении вызова, и возвращаемое значение, которое сообщает отчет библиотеки. ltrace также может отслеживать системные вызовы Linux. –

ответ

1

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

Прежде всего, если вам действительно нужно использовать Ctrl-C, чтобы программа правильно закончить на этом сигнале: Is destructor called if SIGINT or SIGSTP issued?

Затем использовать технику с объекта стека, содержащего указатель ресурса (к функции CloseAPI в Это дело). Затем убедитесь, что этот объект вызовет CloseAPI в своем деструкторе (вы можете проверить, не был ли ранее закрыт CloseAPI). Подробнее см. «Эффективный C++, глава 3: Управление ресурсами».

Это, даже если вы не вызываете CloseAPI, контейнер указателей сделает это за вас.

p.s. вам стоит подумать об этом, даже если вы не собираетесь использовать Ctrl-C. Представьте, что произошло исключение, и ваша программа должна быть остановлена: тогда вы должны быть уверены, что не оставите OS в неопределенном состоянии.