C++ 全局声明时内存泄漏?

C++ 全局声明时内存泄漏?,c++,valgrind,C++,Valgrind,如果不是将指针声明为main的一部分,而是全局声明它们,那么这段代码还会泄漏吗? 我用Valgrind memcheck进行了测试,但没有 class Test1 { public: Test1() { std::cout << "Constructor of Test " << std::endl; } ~Test1() { std::cout << "Destructor of Test " << std::endl; } };

如果不是将指针声明为main的一部分,而是全局声明它们,那么这段代码还会泄漏吗? 我用Valgrind memcheck进行了测试,但没有

class Test1 {
public:
   Test1() { std::cout << "Constructor of Test " << std::endl; }
  ~Test1() { std::cout << "Destructor of Test "  << std::endl; }
};

    //Memory leaked or not when globally declared?
    // Test1 *t1;
    // Test1 *t2;
    // Test1 *t;

int main()
{
    //mem will leak if not deallocated later
    Test1 *t1;
    Test1 *t2;
    Test1 *t;

  try {

    t1=new Test1[100];

    t2=new Test1;
    t =new Test1;

    throw 10;
  }
  catch(int i)
    {
        std::cout << "Caught " << i << std::endl;

        // delete []t1;
        // delete t;
        // delete t2;
    }

    return 0;
}
类Test1{
公众:

Test1(){std::cout声明变量global将使指针变量成为全局变量,而不是指针指向的对象(由于指针位于堆上,它已经是全局的)

因此,您当前的实现也存在漏洞

局部变量在超出范围时会被销毁,但它们指向的不会自动退出。建议:忘记completety
new
delete
运算符,并使用STL或智能指针


编辑:您正在问为什么valgrind没有检测到它,这是一个与原始问题不同的问题(我编辑以添加标记)。

现在您总是在泄漏内存,无论您是在主指针还是全局指针中声明

无论何时在代码中使用
new
,都需要使用
delete
delete[]


<>在现代C++中,使用<代码>新< /COD>被认为是一个坏的实践,如果你想要一个数组,或者使用代码> STD::UnjyQupPT如果你正在管理一个对象的指针,你应该使用<代码> STD::Vector 。指针的作用域和生存期不会影响指针对象的情况,但您已经通过在析构函数中打印说明了这一点

然而,Valgrind的报告略有不同

我使用2个元素的较短数组来运行,以减少输出量

heap summary告诉您在运行结束时堆上仍保留哪些数据,这两个程序都是相同的:

==397== HEAP SUMMARY:
==397==     in use at exit: 12 bytes in 3 blocks
==397==   total heap usage: 6 allocs, 3 frees, 76,944 bytes allocated
这意味着两个程序从未释放对象

然而,Valgrind在“绝对丢失”分配(不引用任何变量中剩余的内存块)和“仍然可访问”分配(保留引用)之间确实存在差异

带有本地指针的泄漏摘要

==397== LEAK SUMMARY:
==397==    definitely lost: 12 bytes in 3 blocks
==397==    indirectly lost: 0 bytes in 0 blocks
==397==      possibly lost: 0 bytes in 0 blocks
==397==    still reachable: 0 bytes in 0 blocks
==397==         suppressed: 0 bytes in 0 blocks
==385== LEAK SUMMARY:
==385==    definitely lost: 0 bytes in 0 blocks
==385==    indirectly lost: 0 bytes in 0 blocks
==385==      possibly lost: 0 bytes in 0 blocks
==385==    still reachable: 12 bytes in 3 blocks
==385==                       of which reachable via heuristic:
==385==                         length64           : 10 bytes in 1 blocks
带有全局指针的泄漏摘要

==397== LEAK SUMMARY:
==397==    definitely lost: 12 bytes in 3 blocks
==397==    indirectly lost: 0 bytes in 0 blocks
==397==      possibly lost: 0 bytes in 0 blocks
==397==    still reachable: 0 bytes in 0 blocks
==397==         suppressed: 0 bytes in 0 blocks
==385== LEAK SUMMARY:
==385==    definitely lost: 0 bytes in 0 blocks
==385==    indirectly lost: 0 bytes in 0 blocks
==385==      possibly lost: 0 bytes in 0 blocks
==385==    still reachable: 12 bytes in 3 blocks
==385==                       of which reachable via heuristic:
==385==                         length64           : 10 bytes in 1 blocks
如果指针是本地的,valgrind可以确保不保留引用,因为在main返回后,堆栈位置不再有效

如果指针是全局的,它们仍然有效,因此仍然可以使用或释放

为什么valgrind会做出这种区分?

特别是在历史上的C程序中,一次分配一些内存并在整个执行过程中使用它可能被认为是合法的,而不必在以后释放内存。一旦程序退出,操作系统将清理程序的整个虚拟内存空间。因此,这可能是一个bug,也可能是故意的. 如果您对此类泄漏感兴趣,valgrind本身会告诉您必须如何调用它来查看这些泄漏:

==405== Reachable blocks (those to which a pointer was found) are not shown. 
==405== To see them, rerun with: --leak-check=full --show-leak-kinds=all                                                                                                                                
“肯定输了”然而,内存总是可疑的,这就是valgrind区分案例的原因。像valgrind这样的工具的价值在于它的精度。报告许多实际错误是不够的,为了有用,它还必须努力产生少量的误报,否则查看报告往往会浪费开发时间私奔一次


<> >在现代C++中,内存泄漏的借口不多,如<>代码>:ST::UnQuyJPPT/<代码>应该是分配动态对象的方法。<代码> STD::vector < /COD>应该用于动态数组和本地对象,因为编译器永远不会忘记分配。即使对于单体,工具输出中的噪声也一样。valgrind和address sanitizer通常比保存一个析构函数调用或解除分配带来的微不足道的好处更重要。

变量的词法范围对销毁时发生的情况没有影响。如果确实需要指针,请使用智能指针。如果不需要指针,请不要使用它们。此外,如果没有引发异常,则不能使用o同时删除指针。你的第一句话意味着本地声明会导致泄漏,而你的第二句话则声称Valgrind说不会。这两句话都是真的吗?MFnx这只是在测试东西。显然,智能指针是一种方法。但我的问题是:为什么Valgrind在这些声明发生时没有检测到泄漏指针是在main之外声明的?如果我注释掉main中声明的指针并取消注释全局声明的指针,Valgrind很高兴并且没有检测到泄漏,正如我上面所说的,很明显的方法是使用智能指针。然而,我只是在测试一些东西并运行它,所以我想我会问,Valgrind为什么没有检测到泄漏呢ng我不知道,但它似乎很容易检测到,因此valgrind设置中可能存在问题。你没有问valgrind为什么没有检测到它,而是问它是否泄漏。Michael Chourdakis感谢你的回答。我将进行调查。再一次,问题不在于我们现在可以使用智能指针。每个人都对此置之不理。问题在于valgrin为什么会这样d没有检测到答案@PaulR。事实上,这就是我现在在valgrind手册中看到的。再次感谢您的回复