【问题标题】:Memory leak in C++ applicationC++ 应用程序中的内存泄漏
【发布时间】:2012-06-24 08:54:57
【问题描述】:

我已经尝试了一千次以在这个 sn-p 中找到 该死的内存泄漏,但我只是惨败...我正在学习内存分配和这些东西我从来没有能够制作一个可以完全释放它的内存的程序......

我正在调用一个 for 循环来分配 140 个 Contato_s 结构并将它们放入 Agenda std::list。然后我调用另一个 for 循环来使用 RemoverContato 和相应的代码删除所有 140 个联系人... Windows 不会报告单个 Kb 的空闲内存!

struct Contato_s
{
    int Codigo;
    std::string Nome, Numero, Email, Apelido;
};

std::list<Contato_s*> Agenda;

void CriarContato(std::string Nome, std::string Numero, std::string Email, std::string Apelido) // Add a contact to the list
{
    Contato_s *temp = new Contato_s; // Criando um contato temporario

    temp->Nome = Nome;
    temp->Numero = Numero;
    temp->Email = Email;
    temp->Apelido = Apelido;
    temp->Codigo = Agenda.size()+1;

    Agenda.push_back(temp); // Adicionando o contato a lista
}

int RemoverContato(int Codigo) // Delete a contact from the list
{
    for (std::list<Contato_s*>::iterator i = Agenda.begin(), e = Agenda.end(); i != e;)
    {
        if((*i)->Codigo == Codigo)
        {
            delete (*i);
            i = Agenda.erase(i);
            return 1;
        } else {
            ++i;
        }
    }
    return 0;
}

提前致谢:)!

--编辑

好的,这就是我试图销毁联系人的方式:

for(int i=0; i<140; ++i)
    {
        if(RemoverContato(1+i) == 0)
            std::cout << "Fail removing contact " << i << std::endl;
        else
            std::cout << "Contact " << i << " removed" << std::endl;
    }

(Ofc 我总是得到“联系人 X 被删除”并且在该部分没有失败,因此理论上正在找到联系人)

【问题讨论】:

  • 嗯,您是否为列表中的每个元素调用RemoverContato?如果你不显示你是如何调用这段代码的,那么我们就没有什么可以告诉你的了(除了 std::list&lt;Contato_s*&gt; 而不是 std::list&lt;Contato_s&gt; 是不必要的愚蠢)。
  • 你需要展示你是如何调用RemoverContato的。 9
  • 您所说的一切都表明内存已泄漏。物理内存由操作系统管理,并且在其他地方需要时始终可以重复使用。虚拟内存是每个进程的,因此不能“返回”。我认为该错误只是您的期望——期望一个进程将虚拟内存返回给系统(这没有任何意义,因为虚拟内存是每个进程的)。
  • 丢失原始指针,改用智能指针。
  • 这个想法是使用原始指针来学习内存分配,所以我认为在这里只使用一些更高级别的抽象是没有意义的:)

标签: c++ memory-management memory-leaks stdlist


【解决方案1】:

您需要确保每个Contato_s 都有一个唯一的Codigo(这是否意味着ID?我将其称为ID)。有可能多个Contato_s 可以共享同一个ID,因为您的ID 基于Agenda 的当前大小(假设您添加了两个联系人,删除了第一个,然后添加了另一个......这两个联系人将具有相同的 ID 2)。您的删除技术只会删除第一个匹配的 ID,而保留其他 ID。在RemoverContato返回成功或失败之前,您应该遍历所有联系人并检查所有ID。

【讨论】:

  • 谢谢,但我刚刚检查了一下,所有的 ID 都是唯一的,但是在创建和删除多次时这会搞砸,所以谢谢,现在 Codigo 创建是真的 独一无二,但即便如此,泄漏仍然存在。
  • 你是如何确定内存泄露的?
  • 嗯,在任务管理器 sysinternals VMMAP 上进行了一些观察,我还在 vmmap 中使用了字符串计数器,它在反复调用 create-destroy 时报告字符串数量一直在增长
  • 你能粘贴一下泄露的代码吗?这里没有创建或销毁任何东西的代码,只有添加和删除的代码。
  • 哦,创建和销毁,这就是我的意思。 “CriarContato”函数通过 new 运算符获取内存,“RemoverContato”函数(试图)通过删除分配的内存来销毁它......
猜你喜欢
  • 1970-01-01
  • 2012-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多