内存溢出?std:: badalloc

Memory Overflow? std::badalloc

本文关键字:badalloc std 溢出 内存      更新时间:2023-10-16

我有一个用欧拉法求解一维布朗运动的程序。作为一个随机过程,我想对许多粒子求平均值。但是我发现,当我增加粒子数量时,它会过载,并且我得到std::badalloc错误,我理解这是内存错误。

这是我的完整代码

#include <iostream>
#include <vector>
#include <fstream>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <ctime>
using namespace std;
// Box-Muller Method to generate gaussian numbers
double generateGaussianNoise(double mu, double sigma) {
    const double epsilon = std::numeric_limits<double>::min();
    const double tau = 2.0 * 3.14159265358979323846;
    static double z0, z1;
    static bool generate;
    generate = !generate;
    if (!generate) return z1 * sigma + mu;
    double u1, u2;
    do {
        u1 = rand() * (1.0 / RAND_MAX);
        u2 = rand() * (1.0 / RAND_MAX);
    } while (u1 <= epsilon);
    z0 = sqrt(-2.0 * log(u1)) * cos(tau * u2);
    z1 = sqrt(-2.0 * log(u1)) * sin(tau * u2);
    return z0 * sigma + mu;
}
int main() {
    // Initialize Variables
    double gg;  // Gaussian Number Picked  from distribution
    // Integrator
    double t0 = 0;  // Setting the Time Window
    double tf = 10;
    double n = 5000;           // Number of Steps
    double h = (tf - t0) / n;  // Time Step Size
    // Set Constants
    const double pii = atan(1) * 4;  // pi
    const double eta = 1;            // viscous constant
    const double m = 1;              // mass
    const double aa = 1;             // radius
    const double Temp = 30;          // Temperature in Kelvins
    const double KB = 1;             // Boltzmann Constant
    const double alpha = (6 * pii * eta * aa);
    // More Constants
    const double mu = 0;  // Gaussian Mean
    const double sigma = 1;  // Gaussian Std Deviation
    const double ng = n;  // No. of pts to generate for Gauss distribution
    const double npart = 1000;  // No. of Particles
    // Initial Conditions
    double x0 = 0;
    double y0 = 0;
    double t = t0;
    // Vectors
    vector<double> storX;  // Vector that keeps displacement values
    vector<double> storY;  // Vector that keeps velocity values
    vector<double> storT;  // Vector to store time
    vector<double> storeGaussian;  // Vector to store Gaussian numbers generated
    vector<double> holder;  // Placeholder Vector for calculation   operations
    vector<double> mainstore;  // Vector that holds the final value desired
    storT.push_back(t0);
    // Prepares mainstore
    for (int z = 0; z < (n+1); z++) {
        mainstore.push_back(0);
    }
    for (int NN = 0; NN < npart; NN++) {
        holder.clear();
        storX.clear();
        storY.clear();
        storT.clear();
        storT.push_back(0);
        // Prepares holder
        for (int z = 0; z < (n+1); z++) {
            holder.push_back(0);
            storX.push_back(0);
            storY.push_back(0);
        }
        // Gaussian Generator
        srand(time(NULL));
        for (double iiii = 0; iiii < ng; iiii++) {
            gg = generateGaussianNoise(0, 1);  // generateGaussianNoise(mu,sigma)
            storeGaussian.push_back(gg);
        }
        // Solver
        for (int ii = 0; ii < n; ii++) {
            storY[ii + 1] =
                storY[ii] - (alpha / m) * storY[ii] * h +
                (sqrt(2 * alpha * KB * Temp) / m) * sqrt(h) * storeGaussian[ii];
            storX[ii + 1] = storX[ii] + storY[ii] * h;
            holder[ii + 1] =
                pow(storX[ii + 1], 2);  // Finds the displacement squared
            t = t + h;
            storT.push_back(t);
        }
        // Updates the Main Storage
        for (int z = 0; z < storX.size(); z++) {
            mainstore[z] = mainstore[z] + holder[z];
        }
    }
    // Average over the number of particles
    for (int z = 0; z < storX.size(); z++) {
        mainstore[z] = mainstore[z] / (npart);
    }
    // Outputs the data
    ofstream fout("LangevinEulerTest.txt");
    for (int jj = 0; jj < storX.size(); jj++) {
        fout << storT[jj] << 't' << mainstore[jj] << 't' << storX[jj] << endl;
    }
    return 0;
}

如你所见,npart是我用来改变粒子数量的变量。但是在每次迭代之后,我确实清除了我的存储向量,如storX,storY..。所以在纸面上,粒子的数量应该不会影响记忆?我只是调用编译器重复多次,并添加到主存储向量mainstore。我在一台4GB内存的电脑上运行我的代码。

如果有人能指出我在逻辑上的错误或提出改进建议,我将不胜感激。

Edit:当前粒子数设置为npart = 1000。因此,当我尝试将其增加到npart = 20000或npart = 50000时,它会给我内存错误。

Edit2我编辑了代码,为每个存储向量分配了一个额外的索引。但是它似乎并没有修复内存溢出

求解器部分存在越界异常。storY的大小为n,然后进入ii+1,从i到n-1。所以对于你的代码提供。storY的大小为5000。允许使用索引0到4999(包括)进行访问,但您尝试使用索引5000进行访问。storX, holdermainstore相同。

另外,storeGaussian在添加新变量之前不会被清除。对于每个npart循环,它增长n。无论如何,您只能在求解器部分访问它的第一个n值。

请注意,vector::clear从vector中删除所有元素,但不一定改变vector的容量(即它的存储数组),参见文档

这不会导致这里的问题,因为您将在下次运行中重用相同的数组,但是在使用vector时需要注意。