“CRT检测到应用程序在堆缓冲区结束后写入内存”?有没有什么办法解决这一问题?

时间:2015-10-19 15:55:37

标签: c++

我的编译器一直告诉我“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;
}

我真的无法想到代码中哪种特定的艺术造成了这个问题?

1 个答案:

答案 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”消息之外);我不知道输出是否正确。