【问题标题】:How to create a memory leak in C++?如何在 C++ 中创建内存泄漏?
【发布时间】:2011-11-06 17:38:42
【问题描述】:

我只是想知道如何使用 C++ 创建系统内存泄漏。我已经对此进行了一些谷歌搜索,但没有发现太多,我知道在 C# 中这样做并不可行,因为它是托管代码,但想知道是否有一种简单的方法可以用 C++ 做到这一点?我只是觉得看看系统由于代码编写不正确而遭受了多少损失会很有趣。谢谢。

【问题讨论】:

  • 在C#中非常可行。一个常见的原因是人们认为它不可行并且不用担心。
  • 哈哈!为狂野而生! :) 不太实际的答案是:只需编写一个中等大小的 C++ 程序,它就会有内存泄漏 :)(只是开玩笑)
  • 什么是“系统内存泄漏”,而不是任何其他类型的内存泄漏?您的意思是要创建一个在程序生命周期之外持续存在的泄漏?当(且仅当)某些实现定义的 API 允许您做一些无限期消耗内核资源的事情时,就会发生这种情况。例如,您可以启动守护进程或类似进程。即使这不是严格“泄露”的,因为它仍然可以通过进程列表访问,并且可以在以后被杀死。
  • @Steve 我只是说一般的内存泄漏,有人已经编辑了一个更好的问题标题

标签: c++ memory-leaks


【解决方案1】:

当您调用new 而不稍后调用相应的delete 时,会发生内存泄漏。如本示例代码所示:

int main() {
    // OK
    int * p = new int;
    delete p; 

    // Memory leak
    int * q = new int;
    // no delete
}

【讨论】:

  • 所以大概会泄漏一次内存,因为新的 int 仍在内存中,如果它处于无限 for 循环中,那么它会泄漏直到程序被杀死?
  • 如果它是一个无限循环,那么它会泄漏“无限”量的内存(直到系统挂起或强制终止进程)。
  • @StackedCrooked 那么这是在 C++ 中发生内存泄漏的唯一方法。 (对不起,我是 C++ 初学者)。
  • @Supertecnoboff 发生内存泄漏的方式有很多种。继续学习:)
【解决方案2】:
  1. 创建指向对象的指针并在堆上分配它
  2. 不要删除它。
  3. 重复前面的步骤
  4. ????
  5. 利润

【讨论】:

  • 创建一个指针是不够的。它必须指向一个堆分配的对象(即使那样,指针也不是很重要)
【解决方案3】:
int main() {
    while(true) new int;
}

【讨论】:

  • 啊,确实如此。我专注于 C#; OP 要求在 C++ 中使用它并不是真正必要的。但是,当然可以用 C++ 回答
  • 为什么不简单地 while(new int); ?
  • @Luchian:作为布尔条件的指针分配?这一点都不简单或清楚。
  • @sehe:问题是如何在 C++ 中创建泄漏——为什么会有人在 C# 中回答?
  • @DeadMG 在设计内存泄漏时我们应该清楚吗? :D 另外,它很简单... new int 返回一个可以评估为布尔值的指针...
【解决方案4】:

内存泄漏有很多种:

  • 分配的内存由于没有指向它而无法释放。
    这类泄漏很容易在 C 和 C++ 中创建。它们也很容易预防、检测和治愈。因为它们很容易检测,所以有很多免费和商业工具可以帮助找到此类泄漏。

  • 应在很久以前释放的仍可访问的已分配内存。
    这类泄漏更难检测、预防或治愈。有些东西仍然指向它,它最终会被释放——例如,就在exit() 之前。从技术上讲,这并不是一个泄漏,但实际上它是一个泄漏。许多所谓的无泄漏应用程序都有这样的泄漏。你所要做的就是运行一个系统配置文件来查看一些愚蠢的应用程序消耗更多的内存。即使在托管语言中,这些类型的泄漏也很容易创建。

  • 分配的内存一开始就不应该分配。
    示例:用户可以轻松地要求 Matlab 创建这些类型的泄漏。 Matlab 在创建此类泄漏方面也相当积极。当 Matlab 从malloc 获取失败时,它会进入一个循环,等待一段时间,然后重试malloc。与此同时,操作系统疯狂地尝试通过将程序块从真实内存转移到虚拟内存来处理内存丢失。最终,一切都在虚拟内存中——一切都陷入了停滞。

【讨论】:

    【解决方案5】:

    只需编写一个分配“大量数据”的应用程序,然后阻塞直到它被杀死。只需运行这个程序并让它继续运行。

    【讨论】:

    • 为什么要在 C++ 中使用 malloc?
    • 为什么要使用 C++ 制作一个泄漏的两行?我正在修复我的答案以使用“分配”而不是 malloc。
    【解决方案6】:

    在 C# 中,只需使用 P/Invoke 分配大量内存、资源句柄并保留它们。

    您可以在简单的 C# 工具中很好地使用非托管代码

    【讨论】:

    • 参见witty-bear 引用的文章,以获得很好的演示
    • 垃圾回收会在代码块结束后删除所有分配的内存
    • @Dr.MinaMounir 仅用于垃圾收集的堆引用。
    • 感谢您的澄清......我在提问时正在阅读的文章只是在谈论委托被垃圾收集而不是分配的内存我误解了它
    • @sehe 他问的是C++,而不是C#
    【解决方案7】:
    class ClassWithLeakedMemory{
    private:
        char* str;
    public:
        ClassWithLeakedMemory(){
            str = new char[100];
        }
    
        ~ClassWithLeakedMemory(){
            cout<<"We are not freeing the dynamically allocated string memory"<<endl;
        }
    
    };
    
    
    class ClassWithNoLeakedMemory{
    private:
        char* str;
    public:
        ClassWithNoLeakedMemory(){
            str = new char[100];
        }
    
        ~ClassWithNoLeakedMemory(){
            cout<<"We are freeing the dynamically allocated string memory"<<endl;
            delete[] str;
            str = null;
    
        }
    
    };
    
    int main() {
        //we are creating an automatic object of the ClassWithleakedMemory
        //when we will come out of the main, this object will be
        //out of scope. hence it will be deleted. so destructor will
        //be called. but in the destructor, we have not specifically
        //deleted the dynamically allocated string.
    
        //so the stack based pointer object str will be deleted but the   memory  
        //it was pointing to won't be deleted. so we will be left with an
        //unreferenced memory. that is memory leak.
        ClassWithLeakedMemory objectWithLeakedmemory;
        ClassWithNoLeakedMemory objectWithNoLeakedmemory;
        return 0;
    }
    

    基于堆栈的指针对象引用两个类中动态分配的内存的方式如下图所示:

    【讨论】:

    • 所以“你不只是想要任何内存泄漏,你想要一个 fancy 内存泄漏,对吧?”不。
    【解决方案8】:

    当不再引用使用new 创建的对象时,必须对其应用delete 运算符。否则,它占用的内存将丢失,直到程序终止。这称为内存泄漏。这是一个插图:

    #include <vector>
    using namespace std;
    
    void memory_leak(int nbr)
    {
       vector<int> *ptrVector = new vector<int>(nbr);
       // some other stuff ...
       return;
    }
    

    如果我们返回而不在对象上调用delete(即delete ptrToVector),则会发生内存泄漏。为避免这种情况,不要在内存堆上分配本地对象,而是使用堆栈分配的变量,因为这些变量会在函数退出时自动清理。要在运行时堆栈上分配向量,请避免使用new(在堆上创建它)和指针。

    【讨论】:

      【解决方案9】:

      就这么简单:⠀⠀⠀

      new int;
      

      【讨论】:

        【解决方案10】:
        #include <stdio.h>
        
        void main(){
        
        for(int i = 0; i < 1000; i++)
        
        double* ptr = (double*)malloc(1000000*sizeof(double))
        
        //free(ptr);
        
        ptr = NULL;
        
        }
        

        注意:散列的代码行在进程分配它并且没有将其返回给操作系统时导致内存泄漏

        【讨论】:

        • 这是否意味着内存减少了?我的意思是分配给应用程序而不返回给操作系统的内存永远不能被其他应用程序使用吗?
        猜你喜欢
        • 2011-09-27
        • 2011-09-22
        • 2013-04-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多