glibc上valgrind的输出在C++中检测到错误

Output of valgrind on glibc detected error in C++

本文关键字:检测 错误 C++ valgrind 输出 glibc      更新时间:2023-10-16

我收到以下错误。

 *** glibc detected *** ./bin/final: malloc(): memory corruption: 0x0000000000baaf20 ***

所以在谷歌上搜索后,我发现了valgrind,并在我的代码上运行了它,但我无法理解它产生的输出。我做错了什么?

==22297== Memcheck, a memory error detector
==22297== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==22297== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==22297== Command: ./bin/final
==22297== 
xxj-00_2-057.pngnew.jpg 0
h ere1 
h ere2 
h ere1 
h ere2 
h ere1 
==22297== Invalid write of size 8
==22297==    at 0x40D6DE: Histogram::resample(int, int, int, std::vector<double, std::allocator<double> >&) (Histogram.cpp:130)
==22297==    by 0x409860: Descriptor::calc(int, int, std::vector<bool, std::allocator<bool> >&) (Descriptor.cpp:100)
==22297==    by 0x4035FF: main (db.cpp:44)
==22297==  Address 0x11ebe2a0 is 0 bytes after a block of size 3,456 alloc'd
==22297==    at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22297==    by 0x40A85F: std::vector<double, std::allocator<double> >::_M_default_append(unsigned long) (new_allocator.h:92)
==22297==    by 0x40D75A: Histogram::resample(int, int, int, std::vector<double, std::allocator<double> >&) (stl_vector.h:592)
==22297==    by 0x409860: Descriptor::calc(int, int, std::vector<bool, std::allocator<bool> >&) (Descriptor.cpp:100)
==22297==    by 0x4035FF: main (db.cpp:44)
==22297== 
--22297-- VALGRIND INTERNAL ERROR: Valgrind received a signal 11 (SIGSEGV) - exiting
--22297-- si_code=80;  Faulting address: 0x0;  sp: 0x402bbee00
valgrind: the 'impossible' happened:
   Killed by fatal signal
==22297==    at 0x38058236: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==22297==    by 0x38021ADC: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==22297==    by 0x38021CCD: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==22297==    by 0x380902A7: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==22297==    by 0x3809F7D5: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
sched status:
  running_tid=1
Thread 1: status = VgTs_Runnable
==22297==    at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22297==    by 0x40A85F: std::vector<double, std::allocator<double> >::_M_default_append(unsigned long) (new_allocator.h:92)
==22297==    by 0x409D8C: Descriptor::calc(int, int, std::vector<bool, std::allocator<bool> >&) (stl_vector.h:592)
==22297==    by 0x4035FF: main (db.cpp:44)

代码很大,但我已经在这里发布了相关部分。

void Descriptor::calc(int patchX,int patchY,vector<bool> &desc){
    double valRange=patchSize*histogramRange; 
    Histogram histogram(-valRange,valRange,xbuck,-valRange,valRange,ybuck,-M_PI,M_PI,tbuck);
    double minGradient=0;
    vector<double> vals;
    int patchBottom = patchY+patchSize;
    int patchRight = patchX+patchSize;
    int centralx = patchX+patchSize/2, centraly = patchY+patchSize/2;
    for(int i=patchX;i<patchRight;i++){
        for(int j=patchY;j<patchBottom;j++){
            if(FUN(norMagnitude,i,j,double) < minPixVal)
                continue;
            double xp = i-centralx, yp = j-centraly;
            double cos_t = cos(FUN(orientation,i,j,double));
            double sin_t = sin(FUN(orientation,i,j,double));
            double xpPrime = xp*cos_t - yp*sin_t;
            double ypPrime = xp*sin_t + yp*cos_t;
            histogram.increment(xpPrime,ypPrime,FUN(orientation,i,j,double),FUN(norMagnitude,i,j,double));
            minGradient++;
        }
    }
    if(minGradient < patchSize*patchSize*minimumEdge) //if atleast 60*60*0.01 pixel are not more than minPixVal then blank patch
        return;
    //Mat patch= norMagnitude(Rect(patchY,patchX,patchBottom-patchY,patchRight-patchX));
    //namedWindow("k",CV_WINDOW_NORMAL);
    //imshow("k",patch);
    histogram.blur(sigma1,sigma2);
    //histogram.show();
    histogram.resample(xbuck2,ybuck2,tbuck2,vals); 
    int hist_size=xbuck2*ybuck2*tbuck2;

    vector<double> arr;
    arr.resize(hist_size);
    cout<<arr.size()<<" "<<vals.size()<<endl;
    copy(vals.begin(),vals.end(),arr.begin());
    sort(arr.begin(),arr.end());
    cout<<"h"<<endl;
    double histTh = arr[(int)(hist_size*(1-threshold))];
    for(int i=0;i<hist_size;i++){
        if(vals[i]>histTh) 
            desc.push_back(1);
        else 
            desc.push_back(0);
    }
}

void Histogram::resample(int xbuck2,int ybuck2,int tbuck2,vector<double>& vals){
vals.resize(tbuck2*xbuck2*ybuck2);
int i = 0;
double tStep = tbuck/(double)tbuck2;
double yStep = ybuck/(double)ybuck2;
double xStep = xbuck/(double)xbuck2;   
    for(double t = 0; t < tbuck; t += tStep) {
      for(double y = 0; y < ybuck; y += yStep) {
        for(double x = 0; x < xbuck; x += xStep) {
          vals[i]=(bFinalValue(x, y, t));
          i++;
        }
      }
    }
}

Valgrind官方文档中有一节介绍如何解释MemCheck的输出
我建议你从这里开始:http://valgrind.org/docs/manual/quick-start.html#quick-start.interpret

在您的情况下,错误Invalid write of size 8表示您正在向越界内存位置写入。错误发生在Descriptor.cpp线路100等调用的Histogram.cpp线路130


这个错误源于您在Histogram::resample函数中使用doubles作为for循环迭代器的事实。在多次操作后,由于舍入错误,双倍值的准确性可能会降低,最终执行的步骤会比最初计划的要多。

这里有一个例子来帮助说明这个问题。这是因为某些数字不能以100%的精度表示为浮点值。是否遇到此错误将取决于循环的上限值以及循环的步长。

valgrind输出告诉您正在向分配的内存块外部的内存位置进行写入,并向您显示发生分配和无效访问的调用堆栈。

我的猜测(请随意在您发布的代码中添加行号)是,违规的Histogram.cpp:130行是行

vals[i]=(bFinalValue(x, y, t));

最有可能的是,对该数组进行迭代的方式存在问题。为此,您使用的是double值,舍入误差会使您超出数组的末尾。

例如,您有一个值tbuck(它的类型是什么?)和tbuck2的组合,这样尽管您计算了tStep = tbuck / (double) tbuck2,条件tStep + tStep + ...(tbuck2 summands)... + tStep < tbuck仍然为真。

您应该使用整数变量来迭代数组,例如,替换

for(double t = 0; t < tbuck; t += tStep) {

带有

for (int it = 0; it < tbuck2; ++it) {
    double t = it * tStep;

以及类似地针对CCD_ 14和CCD_。