我的编译器一直告诉我“CRT检测到应用程序在堆缓冲区结束后写入内存”?有什么方法可以解决这个问题吗?
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <math.h>
using namespace std;
double randomgen(double min, double max)
{
double range = (max - min);
double div = RAND_MAX / range;
return min + (rand() / div);
}
void generateWalk(double *data, int n, double T, double sigma)
{
double Delta = sigma*(sqrt(T/n));
double X;
data[0] = 0;
if(randomgen(0,1)<0.5)
{
X = Delta;
for(int i=1; i<=n; i++)
{
data[i] = data[i-1] + X;
}
}
else
{
X = -Delta;
for(int i=1; i<=n; i++)
{
data[i] = data[i-1] + X;
}
}
}
void ensembledata(double *data, int nperwalk, int nens, double T,double sigma)
{
double *storer = new double[nens];
for (int j=0;j<nens;j++)
{
generateWalk(data,nperwalk,T,sigma);
storer[j]=data[nperwalk-1];
}
for (int k=0;k<nens;k++)
{
data[k-1]=storer[k-1];
}
delete [] storer;
}
void meanvar(double *data,int size, double *mean,double *var)
{
double sum = 0;
double *first = data;
int k = 0;
for(k = 0; k < size; k++)
sum += *data++;
*mean = sum/size;
sum = 0;
data = first;
for(k = 0; k < size; k++)
sum += (*data - *mean)*(*data++ - *mean);
*var = sum/(size - 1);
}
int main()
{
srand((unsigned)time(nullptr));
double *mdata = new double[1000], mean = 0, var = 0;
generateWalk(mdata, 1000, 10, 1);and record last position
ensembledata(mdata, 1000, 1000, 10, 1);
meanvar(mdata, 1000, &mean, &var);
cout << fixed << setprecision(3);
cout << "mean = " << setw(7) << mean << ", var = " << setw(7) << var << endl;
double sigvals[] = {1,2,3,4,5,6,7,8,9};
int i = 0;
for(i = 0; i < 9; i++)
{
ensembledata(mdata, 1000, 1000, 10, sigvals[i]);
meanvar(mdata, 1000, &mean, &var);
cout << "mean = " << setw(7) << mean << ", var = " << setw(7) << var <<
", sigma = " << setw(7) << sigvals[i] << endl;
}
delete [] mdata;
system("PAUSE");
return EXIT_SUCCESS;
}
我真的无法想到代码中哪种特定的艺术造成了这个问题?
答案 0 :(得分:0)
修复语法错误(“并记录最后一个位置”)后,我编译并发出警告:
g++ -std=c++11 -g -Wall -Wextra 33218861.cpp -o 33218861
33218861.cpp: In function ‘void meanvar(double*, int, double*, double*)’:
33218861.cpp:67:49: warning: operation on ‘data’ may be undefined [-Wsequence-point]
sum += (*data - *mean)*(*data++ - *mean);
^
所以我将该行更正为
sum += (*data - *mean)*(*data - *mean); ++data;
然后Valgrind抱怨对无效位置的一些写入:
==17852== Invalid write of size 8
==17852== at 0x400D97: generateWalk(double*, int, double, double) (33218861.cpp:35)
==17852== by 0x40103A: main (33218861.cpp:75)
==17852== Address 0x5a1df80 is 0 bytes after a block of size 8,000 alloc'd
==17852== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17852== by 0x400FE6: main (33218861.cpp:74)
==17852==
==17852== Invalid write of size 8
==17852== at 0x400D34: generateWalk(double*, int, double, double) (33218861.cpp:27)
==17852== by 0x400E23: ensembledata(double*, int, int, double, double) (33218861.cpp:45)
==17852== by 0x401074: main (33218861.cpp:76)
==17852== Address 0x5a1df80 is 0 bytes after a block of size 8,000 alloc'd
==17852== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17852== by 0x400FE6: main (33218861.cpp:74)
==17852==
==17852== Invalid write of size 8
==17852== at 0x400D97: generateWalk(double*, int, double, double) (33218861.cpp:35)
==17852== by 0x400E23: ensembledata(double*, int, int, double, double) (33218861.cpp:45)
==17852== by 0x401074: main (33218861.cpp:76)
==17852== Address 0x5a1df80 is 0 bytes after a block of size 8,000 alloc'd
==17852== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17852== by 0x400FE6: main (33218861.cpp:74)
==17852==
==17852== Invalid read of size 8
==17852== at 0x400E8F: ensembledata(double*, int, int, double, double) (33218861.cpp:51)
==17852== by 0x401074: main (33218861.cpp:76)
==17852== Address 0x5a1dfb8 is 8 bytes before a block of size 8,000 alloc'd
==17852== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17852== by 0x400DED: ensembledata(double*, int, int, double, double) (33218861.cpp:42)
==17852== by 0x401074: main (33218861.cpp:76)
==17852==
==17852== Invalid write of size 8
==17852== at 0x400E92: ensembledata(double*, int, int, double, double) (33218861.cpp:51)
==17852== by 0x401074: main (33218861.cpp:76)
==17852== Address 0x5a1c038 is 8 bytes before a block of size 8,000 alloc'd
==17852== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17852== by 0x400FE6: main (33218861.cpp:74)
==17852==
mean = -1.199, var = 10231.199
==17852== Invalid write of size 8
==17852== at 0x400D97: generateWalk(double*, int, double, double) (33218861.cpp:35)
==17852== by 0x400E23: ensembledata(double*, int, int, double, double) (33218861.cpp:45)
==17852== by 0x401235: main (33218861.cpp:84)
==17852== Address 0x5a1df80 is 0 bytes after a block of size 8,000 alloc'd
==17852== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17852== by 0x400FE6: main (33218861.cpp:74)
==17852==
==17852== Invalid write of size 8
==17852== at 0x400D34: generateWalk(double*, int, double, double) (33218861.cpp:27)
==17852== by 0x400E23: ensembledata(double*, int, int, double, double) (33218861.cpp:45)
==17852== by 0x401235: main (33218861.cpp:84)
==17852== Address 0x5a1df80 is 0 bytes after a block of size 8,000 alloc'd
==17852== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17852== by 0x400FE6: main (33218861.cpp:74)
==17852==
==17852== Invalid read of size 8
==17852== at 0x400E8F: ensembledata(double*, int, int, double, double) (33218861.cpp:51)
==17852== by 0x401235: main (33218861.cpp:84)
==17852== Address 0x5a1ff38 is 8 bytes before a block of size 8,000 alloc'd
==17852== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17852== by 0x400DED: ensembledata(double*, int, int, double, double) (33218861.cpp:42)
==17852== by 0x401235: main (33218861.cpp:84)
==17852==
==17852== Invalid write of size 8
==17852== at 0x400E92: ensembledata(double*, int, int, double, double) (33218861.cpp:51)
==17852== by 0x401235: main (33218861.cpp:84)
==17852== Address 0x5a1c038 is 8 bytes before a block of size 8,000 alloc'd
==17852== at 0x4C2B800: operator new[](unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==17852== by 0x400FE6: main (33218861.cpp:74)
==17852==
所以有三条感兴趣的线:27,35和51.你可能会看到第27行出了什么问题:
for(int i=1; i<=n; i++)
{
// Invalid write ... 0 bytes after a block of size 8,000 alloc'd
data[i] = data[i-1] + X; // line 27
}
将i<=n
更改为i<n
会停止在此处运行数组末尾的代码。
第35行类似。第51行有一个不同的问题:
for (int k=0;k<nens;k++)
{
// Invalid read ... 8 bytes before a block of size 8,000 alloc'd
// Invalid write ... 8 bytes before a block of size 8,000 alloc'd
data[k-1]=storer[k-1]; // line 51
}
您可以看到第一次循环,我们访问data[-1]
。将k=0
更改为k=1
可以避免这种情况。或者我们可能需要将data[k-1]=storer[k-1]
更改为data[k]=storer[k]
以复制所有值;没有足够的评论来理解其意图。
修复这三个问题可以成功完成(除了system
调用的shell中的“PAUSE:not found”消息之外);我不知道输出是否正确。