bison/flex 解析器的 Valgrind memcheck 结果分析

发布于 2024-11-16 15:45:56 字数 1372 浏览 4 评论 0原文

我正在我的程序上运行 memcheck,并试图解决内存问题。

Memcheck 输出:

==29633== 3,443 (128 direct, 3,315 indirect) bytes in 2 blocks are definitely lost in loss record 7 of 8
==29633==    at 0x4A07D2E: operator new(unsigned long) (vg_replace_malloc.c:261)
==29633==    by 0x42027F: PDcbk(cpfrCallbackType_e, Powerdomain*) (NetExtractor.cpp:1243)
==29633==    by 0x413DBA: cpfparse() (cpf.y:120)
==29633==    by 0x42039B: loadCPF(char*) (NetExtractor.cpp:1253)
==29633==    by 0x420E5D: main (NetExtractor.cpp:1399)
==29633== LEAK SUMMARY:
==29633==    definitely lost: 128 bytes in 2 blocks
==29633==    indirectly lost: 3,315 bytes in 10 blocks
==29633==      possibly lost: 0 bytes in 0 blocks
==29633==    still reachable: 16,458 bytes in 3 blocks
==29633==         suppressed: 0 bytes in 0 blocks

NetExtractor 的第 1253 行是:

powerdomainMap.insert(Powerdomain_pair(powerdomain->getName(),new Powerdomain(*powerdomain)));

用于理解代码的信息:

PowerdomainHashMap powerdomainMap;

typedef hash_map<const string, Powerdomain*, strptrhash, strptrequal> PowerdomainHashMap;
typedef pair<const string, Powerdomain*> Powerdomain_pair;

目前我的猜测是,实际上并没有泄漏,因为我仍然可以从哈希映射访问新创建的 powerdomain,而 valgrind 无法看到这一点。

我说得对吗?如果没有有人可以解释我吗?

谢谢,请随意询问代码详细信息,因为我只粘贴了我认为相关的内容,但我可能错过了一些东西。

I am running memcheck on my program and i'm trying to solve the memory issues.

Memcheck output :

==29633== 3,443 (128 direct, 3,315 indirect) bytes in 2 blocks are definitely lost in loss record 7 of 8
==29633==    at 0x4A07D2E: operator new(unsigned long) (vg_replace_malloc.c:261)
==29633==    by 0x42027F: PDcbk(cpfrCallbackType_e, Powerdomain*) (NetExtractor.cpp:1243)
==29633==    by 0x413DBA: cpfparse() (cpf.y:120)
==29633==    by 0x42039B: loadCPF(char*) (NetExtractor.cpp:1253)
==29633==    by 0x420E5D: main (NetExtractor.cpp:1399)
==29633== LEAK SUMMARY:
==29633==    definitely lost: 128 bytes in 2 blocks
==29633==    indirectly lost: 3,315 bytes in 10 blocks
==29633==      possibly lost: 0 bytes in 0 blocks
==29633==    still reachable: 16,458 bytes in 3 blocks
==29633==         suppressed: 0 bytes in 0 blocks

Line 1253 of NetExtractor is :

powerdomainMap.insert(Powerdomain_pair(powerdomain->getName(),new Powerdomain(*powerdomain)));

Info to understand the code :

PowerdomainHashMap powerdomainMap;

typedef hash_map<const string, Powerdomain*, strptrhash, strptrequal> PowerdomainHashMap;
typedef pair<const string, Powerdomain*> Powerdomain_pair;

For now my guess is that there isn't really a leak because i still can access the newly created powerdomain from my hashmap and that valgrind isn't able to see that.

Am I right ? If not can someone explain me ?

Thanks and feel free to ask code details as i only pasted what i thought was relevant but i might have missed something.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧话新听 2024-11-23 15:45:56

好吧,您已经有了指向 Powerdomain 类动态分配对象的指针映射。
哈希映射本身没有分配该内存,因此它不会为您清理它。
您所要做的就是在不需要时自行释放该内存,例如:

for (PowerdomainHashMap::iterator i = powerdomainMap.begin (),
     e = powerdomainMap.end (); i != e; ++i)
{
    delete i->second;
}
powerdomainMap.clear ();

您可能从未这样做过,而 Valgrind 告诉您在程序终止时该内存仍然可以访问。

现在,如果您在应用程序的生命周期内确实需要这些数据,那么就可以了,因为无论如何,操作系统都会在程序退出时清理该内存。但当然,最好是彻底关闭,这样当这个问题成为真正的问题时,您就不会因为误认为正常行为而忽视它。

除此之外,看起来你无论如何都在进行对象复制,所以我认为考虑不显式使用动态内存并让 hash_map 担心它可能是值得的。数据类型声明将如下所示:

typedef hash_map<const string, Powerdomain, strptrhash, strptrequal> PowerdomainHashMap;
typedef pair<const string, Powerdomain> Powerdomain_pair;

希望有帮助。

Well, you have map of pointers to dynamically allocated objects of class Powerdomain.
The hash map itself did not allocate that memory, so it doesn't clean it up for you.
What you have to do is to free that memory yourself once you don't need it, for example:

for (PowerdomainHashMap::iterator i = powerdomainMap.begin (),
     e = powerdomainMap.end (); i != e; ++i)
{
    delete i->second;
}
powerdomainMap.clear ();

You probably never did that and Valgrind told you about that memory still being reachable upon the program termination.

Now, if you really need that data during the life time of your application, then it is OK because OS will clean that memory when program exits anyway. But of course it is much better to do a clean shutdown, so that when this problems becomes a real problem you don't ignore it by mistreating as OK behaviour.

Aside from that, it seems like you are doing object copies anyway so I think it might be worth it to consider not working with dynamic memory explicitly and let hash_map worry about it. The data type declaration will look like this:

typedef hash_map<const string, Powerdomain, strptrhash, strptrequal> PowerdomainHashMap;
typedef pair<const string, Powerdomain> Powerdomain_pair;

Hope it helps.

丢了幸福的猪 2024-11-23 15:45:56

根据 memcheck 的内存泄漏是指在程序生命周期内分配但程序退出时未释放的任何内存块。由于您在 hash_map 中存储了一个指针,因此当 hash_map 被销毁时,该指针将保持未释放状态。您应该在 hash_map 中使用 shared_ptr 或使用接受指针并在集合被销毁时删除它的集合。

A memory leak according to memcheck is any block of memory which was allocated during the program lifetime which is not freed by program exit. Because you're storing a pointer in the hash_map, this pointer is left unfreed when the hash_map is destroyed. You should either use a shared_ptr in the hash_map or use a collection which accepts a pointer and deletes it when the collection is destroyed.

瑕疵 2024-11-23 15:45:56

在每个 valgrind 附带的手册的常见问题解答部分中,有:

我的程序使用 C++ STL 和字符串类。 Valgrind 报告“仍然可到达”内存泄漏,涉及
这些类位于程序的出口处,但应该没有。

首先:放松一下,这可能不是一个错误,而是一个功能。 C++ 标准库的许多实现
使用自己的内存池分配器。相当多的被破坏的对象的内存不是立即被破坏的
释放并返回给操作系统,但保留在池中以供以后重新使用。事实上池没有被释放
在程序退出时导致 Valgrind 报告该内存仍然可达。行为不自由
不过,出口处的池可以称为库的错误。

使用 GCC,您可以通过全局禁用来强制 STL 使用 malloc 并尽快释放内存
内存缓存。提防!这样做可能会减慢您的程序速度,有时甚至会大幅减慢。

• 对于GCC 2.91、2.95、3.0 和3.1,使用带-D__USE_MALLOC 的STL 编译所有源代码。提防!
从版本 3.3 开始,它已从 GCC 中删除。

• 对于 GCC 3.2.2 及更高版本,您应该在之前导出环境变量 GLIBCPP_FORCE_NEW
运行你的程序。

• 在 GCC 3.4 及更高版本中,该变量已更名为 GLIBCXX_FORCE_NEW。

还有其他方法可以禁用内存池:对对象使用 malloc_alloc 模板(不是
可移植,但应该适用于 GCC),甚至编写您自己的内存分配器。但这一切都超出了
本常见问题解答的范围。首先阅读 http://gcc.gnu.org/onlinedocs/libstdc++/ faq/index.html#4_4_leak 如果您
绝对想这么做。但要注意:分配器属于 STL 中比较混乱的部分,人们会去
竭尽全力使 STL 能够跨平台移植。您的解决方案很有可能有效
您的平台,但不是其他平台。

可能你的问题是相关的。

In the FAQ section of the manual that comes with every valgrind, there is:

My program uses the C++ STL and string classes. Valgrind reports ’still reachable’ memory leaks involving
these classes at the exit of the program, but there should be none.

First of all: relax, it’s probably not a bug, but a feature. Many implementations of the C++ standard libraries
use their own memory pool allocators. Memory for quite a number of destructed objects is not immediately
freed and given back to the OS, but kept in the pool(s) for later re-use. The fact that the pools are not freed
at the exit of the program cause Valgrind to report this memory as still reachable. The behaviour not to free
pools at the exit could be called a bug of the library though.

Using GCC, you can force the STL to use malloc and to free memory as soon as possible by globally disabling
memory caching. Beware! Doing so will probably slow down your program, sometimes drastically.

• With GCC 2.91, 2.95, 3.0 and 3.1, compile all source using the STL with -D__USE_MALLOC. Beware!
This was removed from GCC starting with version 3.3.

• With GCC 3.2.2 and later, you should export the environment variable GLIBCPP_FORCE_NEW before
running your program.

• With GCC 3.4 and later, that variable has changed name to GLIBCXX_FORCE_NEW.

There are other ways to disable memory pooling: using the malloc_alloc template with your objects (not
portable, but should work for GCC) or even writing your own memory allocators. But all this goes beyond the
scope of this FAQ. Start by reading http://gcc.gnu.org/onlinedocs/libstdc++/faq/index.html#4_4_leak if you
absolutely want to do that. But beware: allocators belong to the more messy parts of the STL and people went
to great lengths to make the STL portable across platforms. Chances are good that your solution will work on
your platform, but not on others.

Possibly your problem is related.

灯角 2024-11-23 15:45:56

您在插入操作中分配内存,该内存是否已正确释放?

我应该建议使用 STL 容器,它可以最大限度地减少您必须编写的代码量:

#include <unordered_map>
#include <string>
#include <memory>

typedef std::unordered_map<std::string, std::shared_ptr<Powerdomain> > PowerdomainMap;

这应该具有您需要的所有功能以及内置内存安全性。

在 C++98 中,使用 std::tr1::unordered_map 等。

You are allocating memory in your insert operation, does that ever get deallocated properly?

I should recommend using STL containers which minimize the amount of code you have to write:

#include <unordered_map>
#include <string>
#include <memory>

typedef std::unordered_map<std::string, std::shared_ptr<Powerdomain> > PowerdomainMap;

This should have all the functionality you need with built-in memory safety.

In C++98, use <tr1/unordered_map> and std::tr1::unordered_map etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文