(This seems to be again running into issues with reclaiming NC_VLENs and might be possibly addressed by the proposed fix for #2143 )
We are using netcdf-c 4.8.1, and ran into this interesting crash. It seems to happen when
Here is some simplistic reproduction code that both creates the file and then tries to read the variable:
#include <iostream>
#include "netcdf.h"
void checkErrorCode(int status, const char* message){
if (status != NC_NOERR){
std::cout << "Error code: " << status << " from " << message << std::endl;
std::cout << nc_strerror(status) << std::endl << std::endl;
}
}
int main(int argc, const char * argv[]) {
// ================ WRITE ==================
// Setup data
size_t DATA_LENGTHS[2] = {2, 3};
nc_vlen_t data[DATA_LENGTHS[0] * DATA_LENGTHS[1]];
const int first_size = 6;
double first[first_size] = {65, 66, 67, 68, 69, 70};
data[0].p = first;
data[0].len = first_size;
const int second_size = 6;
double second[second_size] = {65, 66, 67, 68, 69, 70};
data[1].p = second;
data[1].len = second_size;
const int third_size = 5;
double third[third_size] = {65, 66, 67, 68, 69};
data[2].p = third;
data[2].len = third_size;
const int fourth_size = 5;
double fourth[fourth_size] = {65, 66, 67, 68, 69};
data[3].p = fourth;
data[3].len = fourth_size;
const int fifth_size = 8;
double fifth[fifth_size] = {65, 66, 67, 68, 69, 70, 71, 72};
data[4].p = fifth;
data[4].len = fifth_size;
const int sixth_size = 4;
double sixth[sixth_size] = {65, 66, 67, 68};
data[5].p = sixth;
data[5].len = sixth_size;
// Open file
int ncid;
int retval;
retval = nc_create("myfile.nc", NC_NETCDF4, &ncid);
checkErrorCode(retval, "nc_create");
// Define vlen type named RAGGED_DOUBLE
nc_type vlen_typeID;
retval = nc_def_vlen(ncid, "RAGGED_DOUBLE", NC_DOUBLE, &vlen_typeID);
checkErrorCode(retval, "nc_def_vlen");
// Define dimensions
int dimid_x;
retval = nc_def_dim(ncid, "xdim", NC_UNLIMITED, &dimid_x);
checkErrorCode(retval, "nc_def_dim (1)");
int dimid_y;
retval = nc_def_dim(ncid, "ydim", 10, &dimid_y);
checkErrorCode(retval, "nc_def_dim (2)");
int dims[2] = {dimid_y, dimid_x};
// Define vlen variable 1
int varid1;
retval = nc_def_var(ncid, "Var1", vlen_typeID, 2, dims, &varid1);
checkErrorCode(retval, "nc_def_var (1)");
// Write vlen variable 1
size_t start1[2] = {0, 1};
ptrdiff_t stride[2] = {1,1};
retval = nc_put_vars(ncid, varid1, start1, DATA_LENGTHS, stride, data);
checkErrorCode(retval, "nc_put_vars (1)");
// Define vlen variable 2
int varid2;
retval = nc_def_var(ncid, "Var2", vlen_typeID, 2, dims, &varid2);
checkErrorCode(retval, "nc_def_var (2)");
// Write vlen variable 2
size_t start2[2] = {0, 2};
retval = nc_put_vars(ncid, varid2, start2, DATA_LENGTHS, stride, data);
checkErrorCode(retval, "nc_put_vars (2)");
retval = nc_close(ncid);
checkErrorCode(retval, "nc_close (1)");
// ================ READ ==================
// open file
retval = nc_open("myfile.nc", NC_NOWRITE, &ncid);
checkErrorCode(retval, "nc_open");
// read vlen variable with the smaller of the offsets
// the length of fixed dimension is 10, and
// the length of unlimited dimension is 5
// (we wrote 3 datapoints with offset of 2 for 2nd var)
const int num_items = 50;
nc_vlen_t* data_read = new nc_vlen_t[num_items];
retval = nc_get_var(ncid, varid1, data_read);
checkErrorCode(retval, "nc_get_var");
retval = nc_free_vlens(num_items, data_read);
checkErrorCode(retval, "nc_free_vlens");
retval = nc_close(ncid);
checkErrorCode(retval, "nc_close (2)");
return retval;
}
To reproduce the crash outside of our code base I had to use some environment variables that mess with memory allocation and release. I.e. on Debian 10:
% setenv MALLOC_CHECK_ 3
% setenv MALLOC_PERTURB_ 204
% ./a.out
free(): invalid pointer
Abort
$ export MallocScribble=1
$ ./a.out
a.out(23741,0x10b7fae00) malloc: enabling scribbling to detect mods to free blocks
a.out(23741,0x10b7fae00) malloc: *** error for object 0xaaaaaaaaaaaaaaaa: pointer being freed was not allocated
a.out(23741,0x10b7fae00) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
(This seems to be again running into issues with reclaiming NC_VLENs and might be possibly addressed by the proposed fix for #2143 )
We are using netcdf-c 4.8.1, and ran into this interesting crash. It seems to happen when
Here is some simplistic reproduction code that both creates the file and then tries to read the variable:
To reproduce the crash outside of our code base I had to use some environment variables that mess with memory allocation and release. I.e. on Debian 10:
And on macOS 11.2.3: