0

我有一个由用 C++ 编写的不同模块组成的应用程序。
其中一个模块用于处理 SunGrid Engine 上的分布式任务。它使用 DRMAA API 来提交和监控网格作业。如果客户端不支持网格,则应使用本地计算机

API libdrmaa.so 的共享对象在编译时链接并在运行时加载。
如果使用我的应用程序的客户端有这个“.so”一切都很好,但如果客户端没有那个,应用程序退出加载共享库失败。
为了避免这种情况,我将 API 调用替换为使用 dlsym() 和 dlopen() 获得的函数指针。现在,如果对 dlopen 的调用没有成功并且我的目标已经实现,我可以使用本地计算机而不是网格。
现在的问题是应用程序现在可以成功运行小型测试用例,但是对于较大的测试用例,它会引发分段错误,而使用动态加载的相同代码可以正常工作。

使用 dlsym() 和 dlopen() 时我是否遗漏了什么?
有没有其他方法可以实现相同的目标?

任何帮助,将不胜感激。

谢谢,

4

3 回答 3

3

加载的代码不太可能是直接问题dlsym()- 从某种意义上说,动态加载使其成为段错误。

它可能正在做的是暴露一个单独的问题,可能是通过移动东西。这可能意味着一个杂散的(未初始化的)指针指向静态链接情况下的“合法”位置,但在动态链接情况下的其他地方 - 并且其他地方会触发段错误。事实上,从长远来看,这对您是有好处的——它表明存在一个问题,否则可能会在很长一段时间内未被发现。

我认为这特别有可能,因为您提到它发生在较大的测试而不是较小的测试中。

于 2009-07-03T15:41:59.923 回答
1

正如 Jonathan Leffler 所说,问题很可能存在于您直接使用 API 的情况下;它只是还没有导致崩溃。

获得 a 的第一步SIGSEGV应该是分析生成的核心转储(或直接在调试器下运行应用程序),并查看它崩溃的位置。我敢打赌 0.02 美元,它在内部的某个地方崩溃了mallocor free,在这种情况下,问题是简单的旧堆损坏,并且有许多堆检查器工具可以帮助您抓住它。Solaris 提供了watchmalloc,这是一个好的开始。

于 2009-07-05T01:14:23.810 回答
0

如果您在 extern "C" 函数中抛出异常,则应用程序必须退出。这是因为 C ABI 没有传播异常的工具。

为了在使用 DLL(或共享库)时解决这个问题,您通常有一个返回 C++ 对象的 C 函数。然后剩下的交互是与从 DLL 返回的那个 C++ 对象。

这种模式建议(我强调建议)类似工厂的对象,因此您的 DLL 应该有一个外部“C”函数,该函数返回一个 void*,您可以将其重新解释为 C++ 工厂对象。

于 2009-07-03T15:30:13.617 回答