【问题标题】:Calling shared libraries without releasing the memory调用共享库而不释放内存
【发布时间】:2015-01-25 09:24:48
【问题描述】:

在 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");

如果我确保在我的代码中,总是在main 函数返回之前调用CloseAPI 函数,那么一切似乎都很好,我可以在下次再次运行该程序。但是,如果我 Ctrl-C 并在程序有时间调用 CloseAPI 之前中断程序,那么在我下次运行程序时,每当我调用任何 API 函数时都会收到返回错误。我没有文档说明这个错误是什么,但我的直觉是,从程序的上次运行开始,库上有某种锁定。唯一能让我再次运行该程序的方法是重新启动我的机器。无法登录和退出。

所以,我的问题是:

1) 如果我的库是共享库,为什么我认为共享库可以由多个程序同时加载时会出现此错误?

2) 如果我预计Ctrl-C 会经常发生,而无法致电CloseAPI,我该如何解决这个问题?

【问题讨论】:

  • 这不是一个真正的解决方案,但是,处理 C-c 的信号处理程序怎么样(和类似的。SIGINT,是吗?)?
  • 正如@keyser 所说,通过signal(2)sigaction(2) 进行信号处理并在处理程序中调用CloseAPI 将是可行的方法。
  • 已尝试使用 ltrace。此工具显示用户态应用程序对共享库的调用。它通过连接到动态加载系统来实现这一点,允许它插入 shims,显示应用程序在调用时使用的参数,以及库调用报告的返回值。 ltrace 还可以跟踪 Linux 系统调用。
  • 您的共享对象 (Kinova.XXX) 似乎制作不正确。主应用程序应该在退出时释放任何共享对象。工具 ltrace 将揭示发生了什么

标签: c++ ubuntu


【解决方案1】:

所以,如果您确实正确使用了这个 api,那么它需要您在使用后进行适当的清理(这对用户来说并不友好)。

首先,如果你真的需要使用Ctrl-C,让程序在这个信号上正常结束:Is destructor called if SIGINT or SIGSTP issued?

然后使用包含资源指针(在本例中指向 CloseAPI 函数)的堆栈对象的技术。然后确保该对象将在其析构函数中调用 CloseAPI(您可能需要检查之前是否未调用 CloseAPI)。在“Effective C++,第 3 章:资源管理”中查看更多信息。

它,即使你不调用 CloseAPI,指针容器也会为你做这件事。

附言即使您不打算使用 Ctrl-C,您也应该考虑这样做。想象一下发生了异常并且您的程序必须停止:那么您应该确保不要让操作系统处于未定义状态。

【讨论】:

    猜你喜欢
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    • 2012-05-03
    • 2014-06-20
    • 2017-05-14
    • 1970-01-01
    相关资源
    最近更新 更多