【问题标题】:Why does memory allocation fail in this situation?为什么在这种情况下内存分配会失败?
【发布时间】:2014-05-31 06:26:35
【问题描述】:

我一直在调试程序,但我仍然无法弄清楚为什么内存分配失败。所以,这是我的部分代码:

for(int k = 0; k < cur_Candidates.size(); k++)  
{
    bool flag = false;
    QuickSI_SGI(cur_Candidates[k],flag, datacodes);         
    if( flag == true )
    {
        CurGlobalVariables.Answers.push_back(cur_Candidates[k]);

    }
}

上面的代码是一个循环,每次调用函数QuickSI_SGI(cur_Candidates[k],flag, datacodes)

据我所知,当函数返回时,分配给该函数的空间将被释放。但是当我调试程序时,我发现使用的内存随着循环的进行而增加。不幸的是,这是一个长循环!在循环的中间,程序失败并警告内存分配失败! 我真的很困惑。


很抱歉我没有在函数QuickSI_SGI()中详细说明,函数中没有“new”或“malloc”语句,我只是在函数中使用了向量,警告是分配内存向量失败。 cur_Candidates 是一个包含整数的向量,CurGlobalVariables.Answerscur_Candidates 相同。 我正在使用 VS2010,CPU:Intel i5,内存:8GB。


函数如下:

Status PrefixQuickSI::QuickSI_SGI(int cur_graphid, bool &flag, QISequence       datacodes[10000])           
{
Status st;
int cur_size, query_size; 
ECVector<char> cur_UsageTab; 
cur_UsageTab.clear(); 
ECVector<SequenceIndex> cur_MappingTab;
cur_MappingTab.clear();
cur_size = CurGlobalVariables._sequence.size();  
int graphsize = cur_size + datacodes[cur_graphid].numOfPrefixNode;
if((graphsize - 1) > m_QueryGraph->V())     
{   
    flag = false;
    return OK;  
}

for(int i = 0; i < m_UsageTab.size(); i ++)   
    cur_UsageTab.push_back(m_UsageTab[i]);
for(int i = 0; i < m_MappingTab.size(); i ++) 
{
    if(i == cur_size)
        cur_MappingTab.push_back(NO_SEQUENCE_INDEX);
    cur_MappingTab.push_back(m_MappingTab[i]);
}

std::vector<_QISymbol>  cur_sequence;
cur_sequence.clear();

for(int i = 0; i < CurGlobalVariables._sequence.size(); i ++)  
    cur_sequence.push_back(CurGlobalVariables._sequence[i]);
int depth = 0;
st = my_QucikSI(cur_sequence, datacodes[cur_graphid], depth, cur_size,cur_UsageTab,cur_MappingTab, flag);

if (flag==true)
{
    return OK;
}       
else
{
    flag = false;
    return OK;
}
return OK;

}

这是另一个功能:

Status  PrefixQuickSI::my_QucikSI(std::vector<_QISymbol> &cur_sequence, QISequence &graphcode, int  &depth, int feature_size, ECVector<char> cur_UsageTab, ECVector<SequenceIndex> cur_MappingTab, bool &flag)
{
Status st;
int vcnt = m_QueryGraph->V();
_QISymbol T;
if(depth == 0)                                      
{
    T.tSymbol = graphcode.sequence[depth]->tSymbol; 
    T.rSymbols.clear();
    for(int i = 0; i < graphcode.sequence[depth]->numOfRSymbol; i++)
    {
        int  v1,v2;
        Label elabel;
        v1 = graphcode.sequence[depth]->rSymbol[i].val;
        v2 = graphcode.sequence[depth]->rSymbol[i+1].val;
        elabel = graphcode.sequence[depth]->rSymbol[i].lable;
        if(m_QueryGraph->getELabel(cur_MappingTab[v1],cur_MappingTab[v2]) != elabel)
        {   
            flag = false;
            return OK;
        }
        T.rSymbols.push_back(graphcode.sequence[depth]->rSymbol[i]);
        T.rSymbols.push_back(graphcode.sequence[depth]->rSymbol[i+1]);
        i++;                

    }
    depth++;
    cur_sequence.push_back(T);

    if(depth == graphcode.numOfPrefixNode)
    {
        flag =true;
        return OK;
    }
    else
    {
        st = my_QucikSI(cur_sequence, graphcode,depth, feature_size, cur_UsageTab, cur_MappingTab, flag);
        if(flag == true)
        {
            return OK;
        }
        else
        {
            flag = false;
            return OK;
        }
    }
}
else
{
    T.tSymbol = graphcode.sequence[depth]->tSymbol;   
    for( int j = 0; j < graphcode.sequence[depth]->numOfRSymbol; ++j )  
    {
        RSymbol rSymbol;
        rSymbol = graphcode.sequence[depth]->rSymbol[j];
        T.rSymbols.push_back(rSymbol);
    } 

    int pV;
    VertexIDSet Vcandiates;

    for( int i = 0; i < vcnt; i++ )
    {
        pV = T.tSymbol.p;       
        if( cur_UsageTab[i] > 0 || m_QueryGraph->getLabel(i) != T.tSymbol.l || m_QueryGraph->getELabel(i, cur_MappingTab[pV]) != T.tSymbol.pl)
            continue;
        Vcandiates.insert(i);
    }
    if(Vcandiates.size() == 0)
    {
        flag = false;
        return OK;
    }

    for( VertexIDSet::const_iterator v = Vcandiates.begin(); v != Vcandiates.end(); v++ ) 
    {
        bool mis_match = false;
        for( std::vector<RSymbol>::const_iterator r = T.rSymbols.begin(); r != T.rSymbols.end(); r++ )
        {
            if( !MatchREntry(cur_sequence, *v, *r) )
            {
                mis_match = true;
                break;
            }
        }
        if( mis_match ) 
            continue;
        cur_MappingTab[feature_size + depth] = *v;
        cur_UsageTab[*v] = 1;
        depth++; 
        cur_sequence.push_back(T);
        if(depth == graphcode.numOfPrefixNode)
        {
            flag = true;
            return OK;
        }
        else
        {
            st = my_QucikSI(cur_sequence, graphcode,depth, feature_size, cur_UsageTab, cur_MappingTab,flag);
            if(flag == true)
            {
                return OK;
            }
            else
            {
                cur_UsageTab[*v] = 0;
                depth--;
                cur_sequence.pop_back();
            }
        }

    }
}

return OK;

}

【问题讨论】:

  • cur_Candidates 中有什么内容? CurGlobalVariables.Answers的定义是什么?
  • QuickSI_SGI 是做什么的?
  • 您已经确定在这个长循环中内存使用量正在增加,因此询问内存分配失败的原因可能没有效率。这有点像问“为什么吃了几天麦片后麦片盒就空了?”
  • 你知道这个函数分配的空间是不是很小?您在哪个平台上运行您的程序?
  • 您知道使用push_back 将内容添加到集合中会在必要时分配内存,并且在长时间循环中重复这样做几乎肯定会导致内存使用量不断增加?如果删除push_back,问题会消失吗?

标签: c++ memory memory-management


【解决方案1】:

在函数中,参数和局部变量在堆栈上分配。

这些变量的内存在函数返回时自动释放。

如果您的函数使用 new 关键字分配内存,则该内存是在堆上分配的,您必须使用 delete 关键字自己释放它。

例如:

void QuickSI_SGI(int value){ // 'value' will be destroyed on return
  string text="Some text";   // 'text' will be destroyed on return
  char* list=new char[10];   // This allocates 10 bytes on the heap
                             //  and a pointer to them on the stack.
                             // The pointer will be destroyed like
                             //  every other local variable, but
                             //  those 10 bytes won't.
  delete list;               // So you need to manually free that
  return;                    //  memory before return
}

【讨论】:

  • 很抱歉我没有提到函数QuickSI_SGI()中没有'new'语句
  • 好吧,有点复杂
  • 当向量超出范围时,它们会销毁它们枚举的每个对象,因此问题可能存在于这些对象的析构函数中。确保您的对象释放它们为向量中使用的每个类分配的所有内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多