C++ valgrind STL 字符串可能存在泄漏

发布于 2024-09-18 14:27:13 字数 1635 浏览 9 评论 0原文

我没有看到下面泄漏的原因。

#include <iostream>
#include <cstdlib>

int fail(const std::string str)
{
    std::cerr<< str << std::endl;
    exit(1);
}

const std::string usage()
{
    std::string a = "a";
    return a;
}   

int main()
{
    fail(usage());
    return 0;
}

Valgrind 说:

==7238== 14 bytes in 1 blocks are possibly lost in loss record 1 of 1
==7238==    at 0x402377E: operator new(unsigned) (vg_replace_malloc.c:224)
==7238==    by 0x40E7C03: std::string::_Rep::_S_create(unsigned, unsigned, 
std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.10)
==7238==    by 0x40E8864: (within /usr/lib/libstdc++.so.6.0.10)
==7238==    by 0x40E89D5: std::string::string(char const*, std::allocator<char> const&) 
(in /usr/lib/libstdc++.so.6.0.10)
==7238==    by 0x80488EC: usage() (main.cpp:12)
==7238==    by 0x804897C: main (main.cpp:18)
==7238== LEAK SUMMARY:
==7238==    definitely lost: 0 bytes in 0 blocks.
==7238==      possibly lost: 14 bytes in 1 blocks.
==7238==    still reachable: 0 bytes in 0 blocks.
==7238==         suppressed: 0 bytes in 0 blocks.

问题出在 failed() 函数中。当它 exit() 时,内存就会泄漏。

如果我注释掉 exit(1);那么就不存在泄漏的可能。

另外,如果我更改签名 int 失败(const std::string str) 到 int failure(const char* str)

那么也不存在可能的泄漏。我不喜欢这个解决方案,因为我正在使用 failed(string + (LINE)) 类型的东西,但无论如何,这里发生了什么?

如果有人能解释,我会很高兴。

谢谢!

(upps。我猜之前也问过同样的问题,抱歉!Valgrind 在为字符串赋值时报告内存泄漏

I do not see the reason of the leak below.

#include <iostream>
#include <cstdlib>

int fail(const std::string str)
{
    std::cerr<< str << std::endl;
    exit(1);
}

const std::string usage()
{
    std::string a = "a";
    return a;
}   

int main()
{
    fail(usage());
    return 0;
}

Valgrind says:

==7238== 14 bytes in 1 blocks are possibly lost in loss record 1 of 1
==7238==    at 0x402377E: operator new(unsigned) (vg_replace_malloc.c:224)
==7238==    by 0x40E7C03: std::string::_Rep::_S_create(unsigned, unsigned, 
std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.10)
==7238==    by 0x40E8864: (within /usr/lib/libstdc++.so.6.0.10)
==7238==    by 0x40E89D5: std::string::string(char const*, std::allocator<char> const&) 
(in /usr/lib/libstdc++.so.6.0.10)
==7238==    by 0x80488EC: usage() (main.cpp:12)
==7238==    by 0x804897C: main (main.cpp:18)
==7238== LEAK SUMMARY:
==7238==    definitely lost: 0 bytes in 0 blocks.
==7238==      possibly lost: 14 bytes in 1 blocks.
==7238==    still reachable: 0 bytes in 0 blocks.
==7238==         suppressed: 0 bytes in 0 blocks.

The problem is in the fail() function. As it exits(), the memory is leaked.

If I comment out exit(1); then there is no possible leak.

Also, if I change the signature from
int fail(const std::string str)
to
int fail(const char* str)

then there is no possible leak as well. I don't like this solution, as I am using fail(string + (LINE)) type of things, but regardless, what is going on here?

I will be happy if someone can explain.

Thanks!

(upps. same question asked before I guess, sorry! Valgrind reports memory leak when assigning a value to a string)

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

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

发布评论

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

评论(2

も让我眼熟你 2024-09-25 14:27:13

当您调用 exit() 时,不会调用自动对象(局部变量)的析构函数。

在您的具体示例中,不会调用 std::string 析构函数,因此 std::string 拥有的内存永远不会被释放。

如果您让 fail() 采用 const char* 则不会发生泄漏,原因是 const char* 没有析构函数;当指针被销​​毁时,没有任何东西被释放。如果指针指向动态分配的内存,则必须在程序退出之前(由您)释放该内存,否则就会出现内存泄漏。如果它指向字符串文字,则不会出现内存泄漏,因为字符串文字具有静态存储持续时间(也就是说,它们在程序的整个生命周期中都存在)。

When you call exit(), the destructors of automatic objects (local variables) do not get called.

In your specific example, the std::string destructor is not called, so the memory owned by the std::string is never deallocated.

The reason there is no leak if you have fail() take a const char* is that there is no destructor for const char*; nothing is deallocated when a pointer is destroyed. If the pointer points to dynamically allocated memory, then that memory must be deallocated (by you) before the program exits, otherwise you have a memory leak. If it points to a string literal, then there is no memory leak because string literals have static storage duration (that is, they exist for the entire lifetime of your program).

彼岸花ソ最美的依靠 2024-09-25 14:27:13

詹姆斯·麦克内利斯已经写了一个正确的答案。但我想补充一些内容:

  1. 以不必调用 exit() 的方式编写软件总是一件好事 - 这可以帮助您改进整体设计,指定和理解对象生命周期(除非在非常特殊的情况下 - 相当低级别的情况..)。

  2. 正如您在这里看到的,这在使用 valgrind 等工具时非常重要! “干净”的关闭程序让您感到安全,然后一切正常,正如您所期望的那样;)在特殊情况下干净的关闭程序应该是每个软件的要求。

您应该考虑抛出异常,而不是调用某些fail()函数。当抛出异常时,堆栈将被展开,因此您的情况下的 std::string 析构函数将被调用。

James McNellis already wrote a correct answer. But I'd like to add some things:

  1. It is always a good thing to write software in a way that it does not have to call exit() - this helps you improve the overall design, specify and understand object lifetimes (except in very special - rather low level - cases..).

  2. As you see here, this is important when using tools like valgrind! A "clean" shutdown procedure makes you feel safe, then everything worked fine, as you expected ;) A clean shutdown procedure in exceptional cases should be a requirement of every software.

You should consider to throw an exception instead of calling some fail() function. When an exception is thrown, the stack will be unwound, so the std::string destructor in your case would be called.

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