泄漏的例外代码C ++

时间:2010-11-12 03:33:57

标签: c++ exception memory-management exception-handling memory-leaks

我一直在处理一个学校项目,其中一项任务是确保它根本不泄漏。所以,我通过valgrind运行我的程序,因为我没有使用任何动态内存分配,我不认为我会找到任何东西。

哎呀,我做到了。 Valgrind给了我这个:

==22107== 16 bytes in 1 blocks are definitely lost in loss record 1 of 4
==22107==    at 0x100038915: malloc (vg_replace_malloc.c:236)
==22107==    by 0x1000950CF: __cxa_get_globals (in /usr/lib/libstdc++.6.0.9.dylib)
==22107==    by 0x100094DCD: __cxa_allocate_exception (in /usr/lib/libstdc++.6.0.9.dylib)
==22107==    by 0x100051D42: std::__throw_out_of_range(char const*) (in /usr/lib/libstdc++.6.0.9.dylib)
==22107==    by 0x100005463: std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::_M_range_check(unsigned long) const (in ./connect3)
==22107==    by 0x100005482: std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >::at(unsigned long) (in ./connect3)
==22107==    by 0x1000016E3: connect3::checkIfPositionIsBaseCase(Position) const (in ./connect3)
==22107==    by 0x100007BD8: Game::evaluate(Position) (in ./connect3)
==22107==    by 0x100007D72: Game::evaluate(Position) (in ./connect3)
==22107==    by 0x1000043B4: main (in ./connect3)
==22107== 
==22107== LEAK SUMMARY:
==22107==    definitely lost: 16 bytes in 1 blocks
==22107==    indirectly lost: 0 bytes in 0 blocks
==22107==      possibly lost: 0 bytes in 0 blocks
==22107==    still reachable: 8,280 bytes in 3 blocks
==22107==         suppressed: 0 bytes in 0 blocks
==22107== Reachable blocks (those to which a pointer was found) are not shown.
==22107== To see them, rerun with: --leak-check=full --show-reachable=yes

好吧,我看了一下它来自我的函数“checkIfPositionIsBaseCase(Position)”。看看这个方法(我的伙伴写的),我真的很惊讶地看到可能导致泄漏的东西。

异常。这是该函数的代码。 (完全相同的是,阅读第一次尝试捕获并且你已经全部阅读过了。)

///
/// checkIfPositionIsBaseCase
///
bool connect3::checkIfPositionIsBaseCase(Position aPosition) const {

    vector< vector< int > > thisP = aPosition.getBoard();

    for( int w = 0; w < thisP.size(); w++ ) {
        for( int h = 0; h < thisP.at(w).size(); h++ ){
            int thisS = thisP.at( w ).at( h );
            if( thisS != 0 ){
                try{
                    if( thisP.at( w - 1 ).at( h - 1 ) == thisS ){
                        if( thisP.at( w - 2 ).at( h - 2 ) == thisS ){
                            return true;
                        }
                    }
                }catch( out_of_range& ){}

                try{
                    if( thisP.at( w ).at( h - 1 ) == thisS ){
                        if( thisP.at( w ).at( h - 2 ) == thisS ){
                            return true;
                        }
                    }
                }catch( out_of_range& ){}

                try{
                    if( thisP.at( w + 1 ).at( h - 1 ) == thisS ){
                        if( thisP.at( w + 2 ).at( h - 2 ) == thisS ){
                            return true;
                        }
                    }
                }catch( out_of_range& ){}

                try{
                    if( thisP.at( w - 1 ).at( h ) == thisS ){
                        if( thisP.at( w - 2 ).at( h ) == thisS ){
                            return true;
                        }
                    }
                }catch( out_of_range& ){}

                try{
                    if( thisP.at( w + 1 ).at( h ) == thisS ){
                        if( thisP.at( w + 2 ).at( h ) == thisS ){
                            return true;
                        }
                    }
                }catch( out_of_range& ){}

                try{
                    if( thisP.at( w - 1 ).at( h + 1 ) == thisS ){
                        if( thisP.at( w - 2 ).at( h + 2 ) == thisS ){
                            return true;
                        }
                    }
                }catch( out_of_range& ){}

                try{
                    if( thisP.at( w ).at( h + 1 ) == thisS ){
                        if( thisP.at( w ).at( h + 2 ) == thisS ){
                            return true;
                        }
                    }
                }catch( out_of_range& ){}

                try{
                    if( thisP.at( w + 1 ).at( h + 1 ) == thisS ){
                        if( thisP.at( w + 2 ).at( h + 2 ) == thisS ){
                            return true;
                        }
                    }
                }catch( out_of_range& ){}
            }
        }
    }
    ///
    /// One possibility
    ///
    for (int i = 0; i < thisP.size(); i++) {
        for (int j = 0; j < thisP.at(i).size(); j++) {
            if (thisP.at(i).at(j) == 0) {
                return false;
            }
        }
    }
    return true;
}

我做了一点阅读,看起来我捕捉异常的事实意味着我在泄漏记忆,但我不知道如何解决这个问题。我怎样才能重构代码,这样我就不会泄漏内存?

2 个答案:

答案 0 :(得分:2)

重要的是理解重复泄漏内存之间的差异(这可能导致耗尽),并且让一些底层支持代码或库具有一次性初始化步骤,以获得它将在程序中使用的一些堆内存运行(在这种情况下,在程序终止时释放/删除内存并不是真正有用或必要的,尝试安排它可能会非常麻烦。)

这里,__ cxa_get_globals似乎在做一次性的malloc。

简短的故事:只要确保在重复调用这些异常时,您不会获得多个未发布的块(或更大的块)....

答案 1 :(得分:2)

异常更好地用于特殊用例,但在这里它们会经常出现(每个外循环至少4次......)

这很容易被重构:

typedef std::vector< std::vector<int> > board_type;

namespace {
  bool check(board_type const& board, int val, int w1, int h1, int w2, int h2)
  {
    if (w1 < 0 || w2 < 0) { return false; }
    if (w1 >= board.size() || w2 >= board.size()) { return false; }
    if (h1 < 0 || h2 < 0) { return false; }
    if (h1 >= board[w1].size() || h2 >= board[w2].size()) { return false; }
    return board[w1][h1] == val && board[w2][h2] == val;
  }
} // anonymous namespace

bool connect3::checkIfPositionIsBaseCase(Position aPosition) const {

  vector< vector< int > > thisP = aPosition.getBoard();

  bool encounteredZero = false;

  for( int w = 0; w < thisP.size(); w++ ) {
    for( int h = 0; h < thisP.at(w).size(); h++ ){
      int val = thisP[w][h];
      if (val == 0) { encounteredZero = true; continue; }

      // Check in all directions with a clock-wise rotation
      if (check(thisP, val, w-1, h-1, w-2, h-2)) { return true; }
      if (check(thisP, val, w  , h-1, w  , h-2)) { return true; }
      if (check(thisP, val, w+1, h-1, w+2, h-2)) { return true; }
      if (check(thisP, val, w+1, h  , w+2, h  )) { return true; }
      if (check(thisP, val, w+1, h+1, w+2, h+2)) { return true; }
      if (check(thisP, val, w  , h+1, w  , h+2)) { return true; }
      if (check(thisP, val, w-1, h+1, w-2, h+2)) { return true; }
      if (check(thisP, val, w-1, h  , w-2, h  )) { return true; }
    }
  }

  return !encounteredZero;
}

那里不会有任何例外:)我也发现更容易验证检查是否正确和详尽...