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