Search code examples
visual-studioc++17access-violationdynamic-arrays

Access violation writing location 0x00000000 in middle of a for loop


I'm trying to use mnist dataset for neural networks but im getting a Access violation writing location 0x00000000

the code is

for (int i = 0; i < length; i++) {
    innerarray = (int8_t*)malloc(width * height);
    for (int j = 0; j < width * height; j++) {
        int8_t value = 0;
        innerarray[j] = value;
    }
    temparray[i] = innerarray;
}
for (int i = 0; i < length; i++) {
    for (int j = 0; j < width * height; j++) {
        int8_t grayscale;
        rf.read((char*)&grayscale, 1);
        temparray[i][j] = grayscale; //error happens here
    }
}

variable values:

int length = 10000;
int width = 28;
int height = 28;

The weird thing is it only happen when i >= 2512. Also replacing grayscale with 0 doesn't work. I can hower set temparray[2512][0] to 0 before the last nested for loop. Like this:

for (int i = 0; i < length; i++) {
        innerarray = (int8_t*)malloc(width * height);
        for (int j = 0; j < width * height; j++) {
            int8_t value = 0;
            innerarray[j] = value;
        }
        temparray[i] = innerarray;
    }
    temparray[2512][0] = 0; //works 
    for (int i = 0; i < length; i++) {
        for (int j = 0; j < width * height; j++) {
            int8_t grayscale;
            rf.read((char*)&grayscale, 1);
            temparray[i][j] = 0; //error still happens here
        }
    }

The full code is:

#include<iostream>
#include<fstream>
#include<cstdint>
#include<cstdlib>
#include<array>

using namespace std;

struct images {
    int32_t height = 0;
    int32_t width = 0;
    int32_t magicnumber = 0;
    int32_t numberofimages = 0;
    int8_t** images[];
    void setimages(int8_t** newimages) {
        delete[] this->images;
        int8_t** images = (int8_t**)malloc(numberofimages);
        int8_t* innerarray;
        for (int i = 0; i < numberofimages; i++) {
            innerarray = (int8_t*)malloc(width * height);
            images[i] = innerarray;
        }
        for (int i = 0; i < numberofimages; i++) {
            for (int j = 0; j < width * height; j++) {
                images[i][j] = newimages[i][j];
            }
        }
    };
};

struct labels {
    int32_t magicnumber = 0;
    int32_t numberoflabels = 0;
    int8_t labels[];
};

int32_t litleendiantobig(int32_t litle) {//reverse works as well
    int32_t big = ((4278190080 & litle) >> 24) + ((255 & litle) << 24) + ((16711680 & litle) >> 8) + ((65280 & litle) << 8);
        return big;
}

images loadimages(string filename, int32_t magicalnumber) {
    ifstream rf(filename, ios::out | ios::binary);
    if (!rf) {
        cout << "Cannot open file! " << filename << endl;
        exit(1);
    }
    int32_t magicnumberoffile;
    rf.read((char*)&magicnumberoffile, 4);
    magicnumberoffile = litleendiantobig(magicnumberoffile);
    if (magicalnumber != magicnumberoffile) {
        cout << "Wrong magic number!" << endl;
        cout << "expected:" << magicalnumber << endl;
        cout << "got:" <<  magicnumberoffile << endl;
        exit(1);
    }
    images img;
    int32_t length;
    rf.read((char*)&length, 4);
    length = litleendiantobig(length);
    img.numberofimages = length;
    int32_t width;
    rf.read((char*)&width, 4);
    width = litleendiantobig(width);
    img.width = width;
    int32_t height;
    rf.read((char*)&height, 4);
    height = litleendiantobig(height);
    img.height = height;
    int8_t** temparray = (int8_t**)malloc(length);
    int8_t* innerarray;

    for (int i = 0; i < length; i++) {
        innerarray = (int8_t*)malloc(width * height);
        for (int j = 0; j < width * height; j++) {
            int8_t value = 0;
            innerarray[j] = value;
        }
        temparray[i] = innerarray;
    }
    for (int i = 0; i < length; i++) {
        for (int j = 0; j < width * height; j++) {
            int8_t grayscale;
            rf.read((char*)&grayscale, 1);
            temparray[i][j] = grayscale; //error happens here
        }
    }
    img.setimages(temparray);
    rf.close();
    return img;
}

int main() {
    images testimages;
    loadimages("t10k-images.bin", 2051);
    cout << testimages.images;
    return 0;
}

I don't now how to solve the problem and can't find it anywhere else. Thanks for helping me out.


Solution

  • Your using malloc has done you in.

     int* array = (int*)malloc(width* height);   // allocate width * height bytes.
    
     array[i] = x;  // Sets the [i] _integer_ of array to x.
                    // but you allocated space for BYTE size elemennts.
    

    The correct way to allocate integers using malloc:

     int* array = (int*)malloc(width* height * sizeof(int));   // allocate width * height ints
    

    Either that or your original intent was to allocate 8 bit pixels. In that case, your pointers should be declared as unsigned char*.

    In either case, when coding in C++, types are important, and using operator new to allocate your arrays would have saved you from these troubles.