управление памятью — вывод valgrind при обнаруженной ошибке glibc в переполнении стека

Я получаю следующую ошибку.

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

Итак, после поиска в Google, я нашел про 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++;
}
}
}
}

1

Решение

Официальная документация Valgrind содержит раздел о том, как интерпретировать вывод MemCheck.
Я хотел бы предложить, чтобы вы начали там: http://valgrind.org/docs/manual/quick-start.html#quick-start.interpret

В вашем случае ошибка Invalid write of size 8 означает, что вы пишете в область памяти вне пределов. Ошибка возникает в Histogram.cpp линия 130 который был вызван Descriptor.cpp линия 100, так далее.


Ошибка связана с тем фактом, что вы используете doubles как ваши итераторы цикла for в Histogram::resample функция. После нескольких операций точность двойного значения может ухудшиться из-за ошибок округления, и в итоге вы будете выполнять больше шагов, чем планировали изначально.

Вот пример, чтобы помочь проиллюстрировать проблему. Это происходит потому, что определенные цифры не может быть представлен как значения с плавающей запятой со 100% точностью. То, столкнетесь ли вы с этой ошибкой или нет, будет зависеть от верхних значений вашего цикла, а также от размера шага вашего цикла.

2

Другие решения

Выходные данные 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;

а также петли для x а также y аналогично, чтобы избежать ошибок округления и, следовательно, неправильного доступа к массиву.

2

По вопросам рекламы [email protected]