识别内存泄漏

Identify the memory leaks

本文关键字:泄漏 内存 识别      更新时间:2023-10-16

我在试着回答过去考试练习中给我的一些试卷问题,但这两个问题不是很确定,任何帮助都非常感谢。(从图片中输入代码,我觉得没问题)。

Q1:找出下面c++代码中的内存泄漏,并解释如何修复它们。(9标志)

#include <string>
class Logger {
    public:
        static Logger &get_instance () {
            static Logger *instance = NULL;
            if (!instance){
                instance = new Logger();
            }
            return *instance;
        }
        void log (std::string const &str){
            // ..log string
        }
    private:
        Logger(){
        }
        Logger(Logger const&) {
        }
        Logger& operator= (Logger const &) {
        }
        ~Logger() {
        }
};
int main(int argcv, char *argv[]){
    int *v1 = new int[10];
    int *v2 = new int[20];
    Logger::get_instance() . log ("Program Started");
    // .. do something
    delete v1;
    delete v2;
    return 0;
}

我的回答是,如果main由于提前返回或抛出异常而永远不会完成执行,则删除将永远不会运行,导致内存永远不会被释放。我一直在做一些阅读,我相信auto_ptr会解决问题?这是否就像改变线条一样简单??:

auto_ptr<int> v1 = new int[10]; 
auto_ptr<int> v2 = new int[20]; 
v1.release();
delete v1;
为什么虚成员比没有虚成员的类的对象需要更多的内存?

A:因为每个虚成员需要一个指针也存储在虚表中,需要更多的空间。虽然这相当于很少的空间增加。

Q1:注意v1和v2是int型指针,分别指向10和20的数组。delete操作符不匹配-即,由于它是一个数组,它应该是

delete[] v1;
delete[] v2;

,释放整个数组。记住始终匹配new[] and delete[]new and delete

我相信你在Q2上已经是正确的了。必须跟踪的虚函数表和相应的指针确实会增加内存消耗。

总结一下:

  1. 显示的程序使用不正确的删除形式有未定义的行为,所以谈论执行的泄漏是无关紧要的

  2. 如果先前的被修复,泄漏将来自:

    • 新Logger ();//总
    • 其他两个新用途,如果随后的new抛出或string actor抛出或…部分日志抛出。
  3. 修复v1和v2 auto_ptr是不好的,你分配了新的[]。您可以使用boost::auto_array或更好地使v array<int, 10>或至少vector<int>。你绝对不会使用release()然后手动删除,而是将其引导到智能指针。

  4. 固定实例很有趣。所呈现的被称为"泄漏的单例",它应该泄漏实例。但是在创建之后要无所不在,以防在程序退出时需要使用它。如果不希望这样做,则不应使用new创建实例,而应直接使用local static或namespace static。

  5. 比较不相容的事物,这个问题的措辞很糟糕。假设它是经过清理的,答案是具有虚拟成员实例的类(很可能)携带一个指向VMT的额外指针。加上VMT本身在除去一些一般开销后,每个虚拟成员有一个条目。后者确实是微不足道的,但前者可能是一个问题,因为具有1字节状态的类可能会拾取8字节指针,并且可能还有7字节的填充。

你的第一个答案是正确的,可以得到学分,但考官可能想要的是Logger *instance的释放

在给定的代码中,instance的内存被分配,但从未被释放。

第二个答案看起来不错。

实例永远不会被删除,您需要在main()中使用delete[]操作符。

Q1:

few gotchyas -

  • 单例模式是非常危险的,例如,它不是线程安全的,两个线程可能进入并创建两个类-导致内存泄漏,包围EnterCriticalSection或其他线程同步机制,仍然是不安全的,不建议使用。
  • 单例类不释放它们的内存,单例类应该重新计数才能真正正确地工作。
  • 在函数内部使用静态变量,甚至比在类中使用静态成员还要糟糕。
    • 你分配new[]和删除没有delete[]

我怀疑你的问题是两件事:-释放单例指针- use delete[]

一般来说,进程清理将清除悬空的东西。

Q2:

你的第二个问题是对的,因为虚成员需要一个使类更大的虚函数表