malloc() 内存损坏,仅写入特定数量的 int 数组

malloc() memory corruption by writing an int array only for a specific amount

我的代码中存在内存损坏

*** Error in `./match': malloc(): memory corruption: 0x0000000001036470 ***
Aborted (core dumped)

St运行gely 在输入大约 30-40 个元素之前不会发生这种情况。 由于我无法弄清楚发生了什么,所以我做了一些研究并了解到 valgrind 是一个不错的选择。我对此很陌生,所以我 运行 valgrind 通过两个选项(不确定那个是否有意义)指向后续代码行:

void match(vector<APD> apdvec_database, const char* OUTPUTFILE, bool EXTRACT_APD_VALUE)
{
    (...)
    const int N = apdvec_database.size();
    vector<vector<double> > cost (N, vector<double>(N,0));
    (...)
    // Calculate amount of edges 
    double number=0;
    double n=N;
    double k=2;

    number=binom(n, k);

    // convert edges
    int node_num;
    long int edge_num;
    int* edges;
    double* weights;
    node_num=N; 
    edge_num=(int)number;
    [line 561:]     edges = new int[2*edge_num];
    weights = new double[edge_num];

    cout << "\t\t " << node_num << " APDs and " << edge_num << " edges calculated" << endl;

    int e=0;
    for(size_t i = 0; i<apdvec_database.size(); i++)
    {
        for(size_t j = 0; j<apdvec_database.size(); j++)
        {   
            if(i!=j)
            {       
                // Assign edges among themselves
    [line 575:]         edges[2*e] = (int)i;
                edges[2*e+1] = (int)j;

                // Use only triangular matrix with diagonals
                if(j>i){ weights[e] = (double)cost[i][j];}
                else{ if((int)+(int)j<node_num) weights[e] = (double)cost[i][j]; }
                e++;
            }
        }
    }

由于输出,我在开头通过 [line] 标记了两个特定的行:输出是:

valgrind 选项:--tool=memcheck --leak-check=yes

==24195==    at 0x40D5CE: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:575)
==24195==    by 0x410866: main (match.cpp:680)
==24195==  Address 0x8be5a38 is 0 bytes after a block of size 11,448 alloc'd
==24195==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195==    by 0x40D4A6: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:561)
==24195==    by 0x410866: main (match.cpp:680)
==24195== 
==24195== Invalid write of size 4
==24195==    at 0x40D5D2: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:576)
==24195==    by 0x410866: main (match.cpp:680)
==24195==  Address 0x8be5a3c is 4 bytes after a block of size 11,448 alloc'd
==24195==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195==    by 0x40D4A6: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:561)
==24195==    by 0x410866: main (match.cpp:680)
==24195== 
==24195== Invalid write of size 8
==24195==    at 0x40D607: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:580)
==24195==    by 0x410866: main (match.cpp:680)
==24195==  Address 0x158e86c8 is 0 bytes after a block of size 11,448 alloc'd
==24195==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195==    by 0x40D4D3: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:562)
==24195==    by 0x410866: main (match.cpp:680)
==24195== 
==24195== Invalid write of size 8
==24195==    at 0x40D5EA: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (match.cpp:579)
==24195==    by 0x410866: main (match.cpp:680)
==24195==  Address 0x158e87a0 is 128 bytes inside a block of size 184 free'd
==24195==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==24195==    by 0x508A5B8: THashList::Delete(char const*) (THashList.cxx:199)
==24195==    by 0x5515ACF: TDirectoryFile::Close(char const*) (TDirectoryFile.cxx:562)
==24195==    by 0x550A549: TFile::Close(char const*) (TFile.cxx:935)
==24195==    by 0x410623: database_irradiated(char const*, bool, std::vector<APD, std::allocator<APD> >&, double&) (match.cpp:317)
==24195==    by 0x410820: main (match.cpp:655)
==24195== 

valgrind 选项:-fno-inline

==23041== Invalid write of size 4
==23041==    at 0x416D17: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041==    by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041==  Address 0x8be5a38 is 0 bytes after a block of size 11,448 alloc'd
==23041==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23041==    by 0x416C6E: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041==    by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041== 
==23041== Invalid write of size 4
==23041==    at 0x416D1B: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041==    by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041==  Address 0x8be5a3c is 4 bytes after a block of size 11,448 alloc'd
==23041==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23041==    by 0x416C6E: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041==    by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041== 
==23041== Invalid write of size 8
==23041==    at 0x416D72: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041==    by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041==  Address 0x158e86c8 is 0 bytes after a block of size 11,448 alloc'd
==23041==    at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23041==    by 0x416C9B: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041==    by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041== 
==23041== Invalid write of size 8
==23041==    at 0x416D45: match(std::vector<APD, std::allocator<APD> >, char const*, bool) (in /home/ben/analysis/APDs/match/Combine/match)
==23041==    by 0x417AA9: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041==  Address 0x158e87a0 is 128 bytes inside a block of size 184 free'd
==23041==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23041==    by 0x508A5B8: THashList::Delete(char const*) (THashList.cxx:199)
==23041==    by 0x5515ACF: TDirectoryFile::Close(char const*) (TDirectoryFile.cxx:562)
==23041==    by 0x550A549: TFile::Close(char const*) (TFile.cxx:935)
==23041==    by 0x417901: database_irradiated(char const*, bool, std::vector<APD, std::allocator<APD> >&, double&) (in /home/ben/analysis/APDs/match/Combine/match)
==23041==    by 0x417A6D: main (in /home/ben/analysis/APDs/match/Combine/match)
==23041== 

有趣的是,通过 valgrind 程序不会卡住。不会抛出 malloc() 而是它甚至以合理的输出成功结束。

我显然忘了在这里进一步评论:尽管如此,我必须清楚地声明每个变量。可能存在冲突,因为我包含了 Cern ROOT 框架。但是无论如何,通过小心地声明每个变量就解决了这个问题。