草庐IT

c++ - 这个C++的内存泄漏在哪里?

coder 2024-02-16 原文

我被告知以下代码正在泄漏内存的几个工具,但我们无法在我们的生活中看到哪里:

HRESULT CDatabaseValues::GetCStringField(ADODB::_RecordsetPtr& aRecordset, CString& strFieldValue,
                                         const char* strFieldName, const bool& bNullAllowed)
{
    HRESULT hr = E_FAIL;

    try
    {
        COleVariant olevar;
        olevar = aRecordset->Fields->GetItem(_bstr_t(strFieldName))->Value;
        if (olevar.vt == VT_BSTR && olevar.vt != VT_EMPTY)
        {
            strFieldValue = olevar.bstrVal;
            hr = true;
        }
        else if ((olevar.vt == VT_NULL || olevar.vt == VT_EMPTY) && bNullAllowed)
        {
            //ok, but still did not retrieve a field
            hr = S_OK;
            strFieldValue = "";
        }
    }
    catch(Exception^ error)
    {
        hr = E_FAIL;
        MLogger::Write(error);
    }
    return hr;
}

我们假设它与 olevar 变体有关,因为泄漏的大小与从记录集中返回的字符串的大小相匹配。

我已经尝试了 olevar.detach() 和 olevar.clear(),两者都没有效果,所以如果这是原因,我该如何释放可能在 GetItem 中分配的内存。如果这不是原因,那是什么?

编辑

我阅读了 Ray 推荐的文章以及与之相关的评论,然后尝试:

HRESULT CDatabaseValues::GetCStringField(ADODB::_RecordsetPtr& aRecordset, CString& strFieldValue,
                                         const char* strFieldName, const bool& bNullAllowed)
{
    HRESULT hr = E_FAIL;

    try
    {
        COleVariant* olevar = new COleVariant();
        _bstr_t* fieldName = new _bstr_t(strFieldName);
        *olevar = aRecordset->Fields->GetItem(*fieldName)->Value;
        if (olevar->vt == VT_BSTR && olevar->vt != VT_EMPTY)
        {
            strFieldValue = olevar->bstrVal;
            hr = true;
        }
        else if ((olevar->vt == VT_NULL || olevar->vt == VT_EMPTY) && bNullAllowed)
        {
            //ok, but still did not retrieve a field
            hr = S_OK;
            strFieldValue = "";
        }
        delete olevar;
        delete fieldName;
    }
    catch(Exception^ error)
    {
        hr = E_FAIL;
        MLogger::Write(error);
    }
    return hr;
}

主要区别在于 olevariant 和 bstr 现在已明确创建和销毁。

这大约使泄漏量减少了一半,但这里仍有一些东西在泄漏。

解决方案?

看了 Ray 关于使用 Detach 的建议,我想到了这个:

HRESULT CDatabaseValues::GetCStringField(ADODB::_RecordsetPtr& aRecordset, CString& strFieldValue,
                                         const char* strFieldName, const bool& bNullAllowed)
{
    HRESULT hr = E_FAIL;

    try
    {
        COleVariant olevar;
        _bstr_t fieldName = strFieldName;
        olevar = aRecordset->Fields->GetItem(fieldName)->Value;

        if (olevar.vt == VT_BSTR && olevar.vt != VT_EMPTY)
        {
            BSTR fieldValue = olevar.Detach().bstrVal;
            strFieldValue = fieldValue;
            ::SysFreeString(fieldValue);
            hr = true;
        }
        else if ((olevar.vt == VT_NULL || olevar.vt == VT_EMPTY) && bNullAllowed)
        {
            //ok, but still did not retrieve a field
            hr = S_OK;
            strFieldValue = "";
        }
        ::SysFreeString(fieldName);
    }
    catch(Exception^ error)
    {
        hr = E_FAIL;
        MLogger::Write(error);
    }
    return hr;
}

根据工具 (GlowCode),这不再泄漏,但我担心在将 SysFreeString 分配给 CString 后对 fieldValue 使用 SysFreeString。它似乎在运行,但我知道这并不表示没有内存损坏!

最佳答案

您必须释放分配给 BSTR 的内存。

参见 article

哦,在将 VARIANT 的 bstr 值分配给 CString 之前,您必须进行分离

strFieldValue = olevar.detach().bstrVal;

然后确保您的 CString 对象及时被正确销毁。

关于c++ - 这个C++的内存泄漏在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1237768/

有关c++ - 这个C++的内存泄漏在哪里?的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby-on-rails - Ruby 中的内存模型 - 2

    ruby如何管理内存。例如:如果我们在执行过程中采用C程序,则以下是内存模型。类似于这个ruby如何处理内存。C:__________________|||stack|||------------------||||------------------|||||Heap|||||__________________|||data|__________________|text|__________________Ruby:? 最佳答案 Ruby中没有“内存”这样的东西。Class#allocate分配一个对象并返回该对象。这就是程序

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. ruby - 这个 ruby​​ 注入(inject)魔术是如何工作的? - 2

    我今天看到了一个ruby​​代码片段。[1,2,3,4,5,6,7].inject(:+)=>28[1,2,3,4,5,6,7].inject(:*)=>5040这里的注入(inject)和之前看到的完全不一样,比如[1,2,3,4,5,6,7].inject{|sum,x|sum+x}请解释一下它是如何工作的? 最佳答案 没有魔法,符号(方法)只是可能的参数之一。这是来自文档:#enum.inject(initial,sym)=>obj#enum.inject(sym)=>obj#enum.inject(initial){|mem

  7. 键删除后 ruby​​ 哈希内存泄漏 - 2

    你好,我无法成功如何在散列中删除key后释放内存。当我从哈希中删除键时,内存不会释放,也不会在手动调用GC.start后释放。当从Hash中删除键并且这些对象在某处泄漏时,这是预期的行为还是GC不释放内存?如何在Ruby中删除Hash中的键并在内存中取消分配它?例子:irb(main):001:0>`ps-orss=-p#{Process.pid}`.to_i=>4748irb(main):002:0>a={}=>{}irb(main):003:0>1000000.times{|i|a[i]="test#{i}"}=>1000000irb(main):004:0>`ps-orss=-p

  8. ruby-on-rails - ActiveRecord::Associations::CollectionProxy 从哪里获取.each 实例方法? - 2

    假设我有模型Topics和Posts,其中Topichas_many:posts和Postbelongs_to:topic。此时我的数据库中已经有了一些东西。如果我进入Rails控制台并输入Topic.find(1).posts我相信我得到了一个CollectionProxy对象。=>#]>我可以对此调用.each以获得枚举器对象。=>#]:each>我对CollectionProxy如何处理.each感到困惑。我意识到它在某些时候是继承的,但我一直在阅读API文档,他们并没有说得很清楚CollectionProxy是从什么继承的,除非我遗漏了一些明显的东西。Thispage似乎并没有

  9. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  10. ruby-on-rails - 闪存消息存储在哪里? - 2

    我以为它们存储在cookie中-但不,检查cookie没有任何结果。session也不存储它们。那么,我在哪里可以找到它们?我需要这个来直接设置它们(而不是通过flashhash)。 最佳答案 它们存储在inyoursessionstore.自rails2.0以来的默认设置是cookie存储,但请检查config/initializers/session_store.rb以检查您是否使用默认设置以外的东西。 关于ruby-on-rails-闪存消息存储在哪里?,我们在StackOverf

随机推荐