double free or corruption error

In the Headerfile I declare:
1
2
3
4
    
    static const int BT=37,WE=345,SN=264;
    int i;
    double *data_array[SN];


In the Implementation File:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//Constructor
  FireWeatherWRF::FireWeatherWRF(){
	  for (int i=0;i<SN;i++) {data_array[i]= new double[WE];}
	  for (int lat=0;lat<SN;lat++){
      for (int lon=0;lon<WE;lon++){
    	  data_array[lat][lon]=0;
      }
    }
    loaded=false;
  }

//Destructor
  FireWeatherWRF::~FireWeatherWRF(){
    for (i=0;i<SN;i++) {delete [] data_array[i];}
    delete [] data_array;
  }
}


First, What is a Double Free or Corruption error?
Second, Where in my code am I Triggering this?
1
2
3
4
5
double *data_array[SN];

//...

delete [] data_array;


You did not allocate data_array with new[], therefore you should not be deleting it.
That was definitely good advice, but even doing that didn't solve the problem- it just moved it... eg it still throws the double free or corruption error, just later. I have since changed my code & still get the error. Here are the changes:

Array declaration
dblptr *data_array;

Pieces of the Implementation File:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  FireWeatherWRF::FireWeatherWRF(){
    data_array = new dblptr[SN];
    for (int i=0;i<SN;i++) {data_array[i]= new double[WE];}
	for (int lat=0;lat<SN;lat++){
        for (int lon=0;lon<WE;lon++){
            data_array[lat][lon]=0;
        }
    }
    loaded=false;
  }

  void FireWeatherWRF::read_WRF(charptr file,int variable){
    // enum variables{LATITUDE=0,LONGITUDE=1,RAIN=2,WIND=3,TEMP=4,RH=5};
    // data date & time
    string filestr=file;
    size_t found =filestr.find("wrfout_d");
    for (int i=0;i<10;i++){date[i]=filestr[int(found)+10+i];}

    NcError err(NcError::silent_nonfatal);

    //Open, read and check file to make sure it's valid
    NcFile dataFile(file,NcFile::ReadOnly);
    if (!dataFile.is_valid()) {cout<<"file is not valid"<<endl;}

    switch (variable){
    case 0:{                                  //south is negative
      //get variable from netcdf file
      NcVar *latitudeVar;
      if (!(latitudeVar=dataFile.get_var("XLAT")))
      {cout<<"could not get pointer to NcVar latitude requested"<<endl;}
      if (!latitudeVar->get(&data_array[0][0],1,SN,WE))
      {cout<<"could not set netcdf variable to class constructur"<<endl;}

      loaded=true;
    }
      break;
}

  FireWeatherWRF::~FireWeatherWRF(){
    for (int i=0;i<SN;i++) {delete [] data_array[i];}
    delete [] data_array;
  }
}


main function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main(){
  char * file_ptr;
  char file_name[100]="../2009122600/wrfout_d3.2009122600.f18.0000.nc";
  file_ptr=file_name;
  enum variables{LATITUDE=0,LONGITUDE=1,RAIN=2,WIND=3,TEMP=4,RH=5};

  FireWeatherWRF latitude;
  cout<<"data is loaded before call: "<<latitude.isLoaded()<<endl;
  latitude.read_WRF(file_ptr,LATITUDE);
  cout<<"data is loaded after call: "<<latitude.isLoaded()<<endl;
  for (int i=0;i<264;i++){
    for (int j=0;j<345;j++){
        cout<<latitude.data_array[i][j]<<" ";
        }
     cout<<endl;
    }
  cout<<"date of file is: "<<latitude.YYYYMMDDHH()<<endl;
  
  return 0;
}


With this output:
data is loaded before call: 0
data is loaded after call: 1
ARRAY OF #'s (too big to post), but it prints a filled array
date of file is: 2009122600
*** glibc detected *** /home/natasha/FWI/FAFS/Debug/FAFS: double free or corruption (!prev): 0x0000000000603860 ***
Last edited on
What is this function if (!latitudeVar->get(&data_array[0][0],1,SN,WE)) trying to do?

Is it trying to load an entire set of 264 x 345 doubles from the file - directly onto the data_array array?

If so - I'm not convinced it is going to work like that.
yes, that is what the function is trying to do. It's all in the netcdf headers & libraries. That's the syntax in all the tutorials & the fact that I start with an array of all zeros & produce an output array of mostly all zeros, I am fairly sure that it is in fact filling the array.
My thinking is as follows:
If you create a 2d array the way you did using this method:
1
2
3
FireWeatherWRF::FireWeatherWRF(){
    data_array = new dblptr[SN];
    for (int i=0;i<SN;i++) {data_array[i]= new double[WE];}

then the array will not be contigious - it will be disjointed - sou you could not copy a contigious array of data onto it.

An standard C/C++ array such as array[10][15] IS contigious so it could be done.

But I'm thinking about it..
+1 guestgulkan

that code does not properly fill the array. Instead it badly corrupts memory.

You can't use a nested new (pointer to a pointer) array as a 1D array. As guestgulkan said, the elements are not contiguous, but each row is stored seperately in memory.

Obligatory link: http://cplusplus.com/forum/articles/17108/ (specifically, read the 2nd section... the one about "nested new")
THANK YOU! You guys are always so helpful- for those of you reading this with a similar problem, here was my fix:

Array declaration in Header:
double (*data_array)[345];

Implementation file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Constructor
  FireWeatherWRF::FireWeatherWRF(){
    data_array=new double [264][345];
	for (int lat=0;lat<264;lat++){
        for (int lon=0;lon<345;lon++){
            data_array[lat][lon]=0;
        }
    }
    loaded=false;
  }

//Destructor
  FireWeatherWRF::~FireWeatherWRF(){
    delete [] data_array;
  }


in a class you don't want most of your objects to be accessible (so make the private), but to check that the array filled i made it public, so i can call it- this will also provide you with an example of how to call the array if you aren't creating a class:

1
2
3
4
5
6
  for (int i=0;i<264;i++){
    for (int j=0;j<345;j++){
        cout<<latitude.data_array[i][j]<<" ";
        }
        cout<<endl;
    }


For an explanation of what "double (*p)[3][4] = new double [2][3][4]" means, see: http://www.cplusplus.com/forum/beginner/21933/
Topic archived. No new replies allowed.