【问题标题】:Memory still reachable bug fixed, but why?内存仍然可以访问的错误已修复,但为什么呢?
【发布时间】:2013-10-11 17:25:40
【问题描述】:

我正在尝试使用共享库来构建模块化程序。

有两个cpp文件要编译:

共享库,编译用

g++ -fPIC -shared module.cpp -o module.so

//module.cpp
#include <iostream>

使用共享库的文件,编译使用

g++ src/main.cpp -ldl -o 二进制

g++ -DFIX src/main.cpp -ldl -o 二进制

//main.cpp
#include <dlfcn.h>
#ifdef FIX
# include <iostream>
#endif

int main()
{
   void* h = dlopen("./module.so", RTLD_LAZY);
   if ( h )
   {
      dlclose(h);
   }
}

FIX 未定义,valgrind 报告大量仍可访问的内存(5,373 字节),FIX 定义,没有内存泄漏。

在共享库中使用iostream 有什么问题?

g++-4.6、g++-4.7 和 g++-4.8 会出现此问题。 g++-4.4 没有显示这种行为。遗憾的是,我没有其他编译器可供测试(因此我不想切换到 g++-4.4)。

更新:

使用附加标志-static-libstdc++ -static-libgcc 编译共享库文件可以减少泄漏块的数量,但不能完全减少。 -static-libgcc 单独没有效果,-static-libstdc++ 有一些效果,但效果不如两者。

【问题讨论】:

  • 最大的问题是:你为什么对在应用程序退出时释放内存如此挂念 - 操作系统本身将在微秒后释放内存?除非你只是在满足你的好奇心,否则这完全没有意义。在后一种情况下,调试器是你的朋友。跟踪分配了哪些内存以及释放了哪些内存,然后您应该看到哪些运行时代码调用了释放,甚至可以找出它没有被释放的原因。调试器,他们工作。
  • 基本上,内存泄漏只是在应用程序运行时发生的泄漏。当应用程序退出时,它们不再泄漏。换句话说:如果它应该在应用程序的正常运行期间被释放,那么你就有了真正的泄漏。如果它在应用程序承诺退出时被释放,您不必担心。
  • @KubaOber 这正是我讨厌的态度。我不在乎操作系统在执行我的应用程序之后 做了什么。我关心我的应用程序。如果有任何一点点导致废话发生(泄漏,UB),我想消除它。没有人应该编写泄漏的代码。这是错误的来源。
  • @stefan:我认为你很幸福地没有意识到 Valgrind 带有一大堆“忽略这个和那个”。您所看到的基本上是列表中缺少的内容。当您禁用这些抑制时,输出将非常冗长,以至于处于无用的边缘。这个禁止列表完全是你所关注的东西,它基本上是通过运行在 your 代码中没有泄漏的合理程序并添加所有库泄漏来创建的到压制。
  • @KubaOber 我知道 valgrind 确实会产生误报,它只是另一个无法完美运行的软件(可以理解,因为它非常复杂)。我是一个完美主义者w.r.t。软件。如果我能理解一个问题,我就会解决它。如果我不能,我问直到我明白,然后解决它。这真是个问题。

标签: c++ linux memory-leaks g++ shared-libraries


【解决方案1】:

1。这段代码 sn-p 为什么或如何“修复”问题?

我不确定为什么不深入研究 libstdc++ 代码,但我假设 iostreams 库分配的内存在整个程序期间一直分配,当它被 valgrind 报告为问题时在共享库中分配,但在主程序中分配时不分配。

2。什么等效的、独立的(来自标准库的)代码 sn-p 提供了相同的错误修复?

首先,我不知道你为什么想要一些“独立于标准库”的东西,而仍然可以访问的内存可能是由标准库分配的。解决方法是要么在任何地方完全不使用标准库,要么以不同的方式使用它。

其次,“修复”是未定义的行为,因为您将std::ios_base 重新定义为与标准库中的正确定义不同,从而违反了单一定义规则。

获得相同行为的正确方法是在您的main.cpp 文件中使用#include &lt;iostream&gt;,其中&lt;iostream&gt; 定义了一个static std::ios_base::Init 对象。或者,只需 #include &lt;ios&gt;,然后定义 static 变量(但不要重新定义 std::ios_base 类型),但这基本上就是 &lt;iostream&gt; 所做的,所以你不妨使用它。

【讨论】:

  • 跟glibc没关系,是libstdc++。我最初的答案错过了第一个问题的答案,我现在把它放回去了
  • 如果问题不涉及module_core.so(包括&lt;iostream&gt;),您应该首先展示进一步简化的示例
  • 我无法使用 G++ 4.7.3 或 4.8.1 与您的原始 module_core.cpp 代码或使用 dlopen(NULL, RTLD_LAZY) 重现 valgrind 结果
  • ...所以也许你是对的,它是由你的 glibc 引起的,或者你缺少 glibc allcoations 所需的 valgrind 抑制文件,在这种情况下,我不知道为什么 @987654334 @object 改变任何东西
  • 你说得对,iostream 导致了这个问题,我现在明白了。我已经完全重写了我的问题来解决这个问题。
猜你喜欢
  • 2023-03-29
  • 2021-05-16
  • 1970-01-01
  • 2012-08-23
  • 2020-12-28
  • 2010-10-08
  • 1970-01-01
  • 1970-01-01
  • 2011-04-29
相关资源
最近更新 更多