I am relatively new to C , and I'm trying to write a simple code to solve a partial differential equation.
The solution code is repeated a number of times with a different value of a time increment dt. During the fifth iteration (j=4), my IDE throws an error:
Exception has occurred. EXC_BAD_ACCESS (code=2, address=0x7ffeeecbd490)
when it is trying to assign a value to a double array called u2. The error specifically occurs on the line:
u2[0] = 1;
From some debugging, I noticed that Visual Studio Code does something different during the reinitialization of u2 on the previous line. When j = 0, 1, 2, and 3, the variables list shows u2 as all zero values after
double u2[numTimes[j]];
When j = 4, suddenly u2's elements are shown as "??". This suggested to me that maybe the reinitialization didn't occur as expected. For instance, maybe dt caused the size of u2 to be larger than c can handle? Some googling disagrees that I hit a size limit at 1,000,000 elements. What is going on here?
Edit: When I looked into std::vector, the just typing
vector<double> u1[1000000];
caused the exact same error message. It therefore doesn't seem that std::vector is a solution. Should I dynamically update u1 and u2 up to the desired number of elements rather than preallocating? I don't see why that would be any more possible though.
Edit 2:
To preallocate memory for a vector, do this:
std::vector<double> u;
u.reserve(1000000);
Do not do this:
std::vector<double> u[1000000];
The array style memory allocation results in the same problem as the original implementation had because you are creating a million vectors not a vector of 1,000,000.
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
// Global System Parameters
double g = 9.81;
double R = 9.81;
double f_du1dt(double u2)
{
return // some equation;
}
double f_du2dt(double u1)
{
return // some other equation;
}
int main()
{
double dt[] = {1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001};
int numDts = sizeof(dt) / sizeof(dt[0]);
double tmax = 10;
int numTimes[numDts];
for (int k = 0; k < numDts; k )
{
numTimes[k] = tmax / dt[k] 1;
}
// Iterate through all dts
for (int j = 0; j < numDts; j)
{
double u1[numTimes[j]];
u1[0] = 0;
double u2[numTimes[j]];
u2[0] = 1;
double du1dt;
double du2dt;
// cout << numTimes << endl;
// Euler Integrator
for (int i = 0; i < numTimes[j]; i )
{
du1dt = f_du1dt(u2[i]);
du2dt = f_du2dt(u1[i]);
u1[i 1] = u1[i] du1dt * dt[j];
u2[i 1] = u2[i] du2dt * dt[j];
}
/*
Output to a csv file to plot
*/
// Open a file called P4output.csv
std::ofstream myFile;
char filename[50];
int n = sprintf(filename,"P4output dt = %d.csv",dt[j]);
myFile.open(filename);
// Write comma separated values to the file
myFile << "time,phiDot,phi" << endl;
for (int i = 0; i < sizeof(u1) / sizeof(u1[0]); i )
{
myFile << dt[j] * i << "," << u1[i] << "," << u2[i] << "," << endl;
}
// Close the file
myFile.close();
}
return 0;
}
CodePudding user response:
When j is 4, your numTimes[k] should be 100001. You're allocating 2 arrays of double at that size on your stack. That puts it at 1.6MB approx. That may exceed your stack size in some environments. It's going to get worse for higher values of j.
I suggest to not use variable length arrays that are allocated on stack. Use std::vector instead that can automatically allocate and re-allocate memory as needed to fit itself.
