Проблема с использованием процедур динамической загрузки C.
-
21-08-2019 - |
Вопрос
У меня есть приложение, состоящее из разных модулей, написанных на C++.
Один из модулей предназначен для решения распределенных задач на SunGrid Engine.Он использует API DRMAA для отправки и мониторинга заданий сетки. Если клиент не поддерживает сетку, должна использоваться локальная машина
Общий объект API libdrmaa.so связывается во время компиляции и загружается во время выполнения.
Если клиент, использующий мое приложение, имеет это ».
Чтобы избежать этого, я заменил вызовы API указателями на функции, полученными с помощью dlsym() и dlopen().Теперь я могу использовать локальную машину вместо сетки, если вызов dlopen не увенчался успехом и моя цель достигнута.
Проблема теперь в том, что приложение теперь успешно работает для небольших тестовых случаев, но в более крупных тестовых случаях оно выдает ошибку сегментации, в то время как тот же код, использующий динамическую загрузку, работает правильно.
Я что-то упустил при использовании dlsym() и dlopen()?
Есть ли другой способ достичь той же цели?
Любая помощь будет оценена по достоинству.
Спасибо,
Решение
Очень маловероятно, что это будет прямая проблема с кодом, загруженным через dlsym()
- в том смысле, что динамическая нагрузка делает его сег-разломом.
Возможно, он выявляет отдельную проблему, вероятно, перемещая вещи.Вероятно, это означает случайный (неинициализированный) указатель, который указывает где-то «законно» в случае статической ссылки, но где-то еще в случае динамической ссылки - и где-то еще вызывает ошибку сегмента.Действительно, в долгосрочной перспективе это принесет вам пользу: это покажет, что существует проблема, которая в противном случае могла бы оставаться незамеченной в течение длительного времени.
Я считаю это особенно вероятным, поскольку вы упомянули, что это происходит с более крупными тестами, а не с маленькими.
Другие советы
Как говорит Джонатан Леффлер, проблема, скорее всего, существует в том случае, если вы используете API напрямую;просто это еще не привело к сбою.
Ваш самый первый шаг, когда вы получаете SIGSEGV
следует проанализировать полученный дамп ядра (или просто запустить приложение непосредственно под отладчиком) и посмотреть где оно сломалось.Ставлю 0,02 доллара, что где-то внутри он рушится. malloc
или free
, и в этом случае проблема заключается в старом старом повреждении кучи, и существует множество инструментов проверки кучи, которые помогут вам ее обнаружить.Солярис предоставляет watchmalloc
, что является хорошим началом.
Если вы генерируете исключение во внешней функции «C», приложение должно закрыться.Это связано с тем, что C ABI не имеет средств для распространения исключений.
Чтобы противостоять этому при использовании DLL (или общих библиотек), у вас обычно есть одна функция C, которая возвращает объект C++.Затем оставшееся взаимодействие происходит с объектом C++, который был возвращен из DLL.
Этот шаблон предполагает (и я подчеркиваю, предполагает) объект, подобный фабрике, поэтому ваша DLL должна иметь одну внешнюю функцию «C», которая возвращает void*, который вы можете переинтерпретировать_cast<> обратно в объект фабрики C++.