1

Trying to work out why i get a error when using delete on this array pointer?

Trying to load png images not sure whats going on

The error is when using delete[] chunks;

The code

typedef struct {
    char r;
    char g;
    char b;
    char a;
} pixel;

class chunk {
public:
    unsigned char length[4];
    unsigned char type[4];
    unsigned char* data;
    unsigned char CRC[4];

    ~chunk()
    {
        delete[] data;
    }
};

class PNG
{
public:
    PNG();
    PNG(std::string filename);
    ~PNG();
    void loadFile(std::string filename);
    pixel* get();
private:
    pixel * img;
    int width;
    int height;
    int bitdepth;
    int colourtype;
    int compressionmethod;
    int filtermethod;
    int interlacemethod;

    unsigned char* data;
    std::ifstream* file;

    int char2int(unsigned char* arr, int start);
};

void PNG::loadFile(std::string filename)
{
    file = new std::ifstream(filename.c_str(), std::ios::in | std::ios::binary);

    size_t size = 0;
    file->seekg(0, std::ios::end);
    size = file->tellg();
    file->seekg(0, std::ios::beg);

    data = new unsigned char[size];
    file->read((char*)data, size);

    /*
    for (int i = 0; i < size; i++) {
    std::cout << std::hex;
    std::cout.width(2);
    std::cout.fill('0');
    std::cout << (int)data[i] << std::endl;
    }
    */

    size_t index = 8; // ignore header
    chunk* chunks = new chunk[size];

    size_t chunkindex = 0;
    while (index < size) {
        for (int i = 0; i < 4; i++) {
            chunks[chunkindex].length[i] = data[index++];
        }
        std::cout << "Size of Chunk " << chunkindex + 1 << ": " << char2int(chunks[chunkindex].length, 0) << std::endl;
        chunks[chunkindex].data = new unsigned char[char2int(chunks[chunkindex].length, 0)];

        for (int i = 0; i < 4; i++) {
            chunks[chunkindex].type[i] = data[index++];
        }

        if (char2int(chunks[chunkindex].length, 0) != 0) {
            for (int i = 0; i < char2int(chunks[chunkindex].length, 0); i++) {
                chunks[chunkindex].data[i] = data[index++];
            }
        }

        for (int i = 0; i < 4; i++) {
            chunks[chunkindex].CRC[i] = data[index++];
        }

        chunkindex++;
    }

    for (int i = 0; i < chunkindex; i++) {
        char name[5];
        for (int j = 0; j < 4; j++) {
            name[j] = chunks[i].type[j];
        }
        name[4] = '\0';

        if (strcmp(name, "IHDR") == 0) {
            std::cout << "FOUND IHDR" << std::endl;
            width = char2int(chunks[i].data, 0);
            height = char2int(chunks[i].data, 4);
            bitdepth = chunks[i].data[8];
            colourtype = chunks[i].data[9];
            compressionmethod = chunks[i].data[10];
            filtermethod = chunks[i].data[11];
            interlacemethod = chunks[i].data[12];

        }
        else if (strcmp(name, "PLTE") == 0) {
            std::cout << "FOUND PLTE" << std::endl;
        }
        else if (strcmp(name, "IDAT") == 0) {
            std::cout << "FOUND IDAT" << std::endl;
        }
        else if (strcmp(name, "IEND") == 0) {
            std::cout << "FOUND IEND" << std::endl;
        }

    }


    std::cout << "Width: " << width << std::endl;
    std::cout << "Height: " << height << std::endl;

    delete[] chunks;
}

error: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF

7
  • 2
    See stackoverflow.com/help/on-topic, your question is off topic without an MCVE. Commented Mar 9, 2018 at 8:55
  • 1
    1) Please provide minimal reproducible example. 2) "The error is when using delete[] chunks;" And the error is..? 3) Did you try stepping through your code with a debugger? Commented Mar 9, 2018 at 8:56
  • 1) As @AlgirdasPreidžius suggested, try using a debugger. If you are under Windows, I suggest Visual Community (free for a one-man project and very good at tracking memory issues.) 2) I also recommend you not to use raw allocations but containers or smart-pointers, in order to prevent memory leaks in case of exceptions... Have a look to the RAII principles here. Commented Mar 9, 2018 at 9:03
  • Regarding your edit: Not every chunk::data from chunks is initialized, due to multiple increments of index during the single iteration of the loop. Commented Mar 9, 2018 at 9:09
  • index, chunkindex, size - these 3 variables look very suspect. The loop limit is index<size, the array is dimensioned as [size] but accessed with chunkindex which is not limited to size. Commented Mar 9, 2018 at 9:10

2 Answers 2

5

Add default constructor to your chunk class.

chunk::chunk () {
   data = 0;
}

When you call

    chunk* chunks = new chunk[size];

size objects were created and all created objected have junk data in data variable - this member is uninitialized. When you call

    delete[] chunks;

for each object of chunks array dtor is called, but when data member is not set - delete[] data is undefined behaviour.

data member was not set for all objects in your chunks array - see at your while loop: you allocate memory for data member in this line

        chunks[chunkindex].data = new unsigned char[char2int(chunks[chunkindex].length, 0)];

but not for all created objects because in your while loop per one iteration index is increased multiple times but chunkindex only once. When while loop is stopped by this contidion index < size, chunkIndex is not equal size it means there are chunk objects with unitialized data member.

Sign up to request clarification or add additional context in comments.

Comments

0

You do not need to use all those pointers in your code. For that application, in my opinion, you should resort to std::vector to help you with memory management. And, you do have a memory leak --- you are allocating std::ifstream object, and you are not releasing it with a matching delete. Well, maybe you are doing it in the destructor of PNG, which we do not see, but anyways you are not closing the file you have opened. You should release the resources (in this case, the opened file) back to the system.

For the code excerpt you pasted, maybe you should have something similar to the below, by changing the bare pointers to std::vectors and changing the file member to be an object rather than a pointer:

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

typedef struct {
  char r;
  char g;
  char b;
  char a;
} pixel;

class chunk {
public:
  unsigned char length[4];
  unsigned char type[4];
  // unsigned char *data;
  /* let std::vector take care of memory issues */
  std::vector<unsigned char> data;
  unsigned char CRC[4];

  // ~chunk() { delete[] data; }
};

class PNG {
public:
  PNG();
  PNG(std::string filename);
  ~PNG();
  void loadFile(std::string filename);
  pixel *get();

private:
  // pixel *img;
  /* std::vector to the help */
  std::vector<pixel> img;
  int width;
  int height;
  int bitdepth;
  int colourtype;
  int compressionmethod;
  int filtermethod;
  int interlacemethod;

  /* please ! */
  // unsigned char *data;
  std::vector<unsigned char> data;
  // std::ifstream *file;
  /* you don't need a pointer here */
  std::ifstream file;

  int char2int(unsigned char *arr, int start);
};

void PNG::loadFile(std::string filename) {
  file = std::ifstream(filename, std::ios::in | std::ios::binary);

  /* better to check whether file is opened properly */
  // if (file) { ... }
  size_t size = 0;
  file.seekg(0, std::ios::end);
  size = file.tellg();
  file.seekg(0, std::ios::beg);

  data = std::vector<unsigned char>(size);
  file.read(reinterpret_cast<char *>(&data[0]), size);

  /* apparently you are done with the file */
  file.close();

  /*
  for (int i = 0; i < size; i++) {
  std::cout << std::hex;
  std::cout.width(2);
  std::cout.fill('0');
  std::cout << (int)data[i] << std::endl;
  }
  */

  size_t index = 8; // ignore header
  std::vector<chunk> chunks(size);

  size_t chunkindex = 0;
  while (index < size) {
    for (int i = 0; i < 4; i++) {
      chunks[chunkindex].length[i] = data[index++];
    }
    std::cout << "Size of Chunk " << chunkindex + 1 << ": "
              << char2int(chunks[chunkindex].length, 0) << std::endl;
    chunks[chunkindex].data =
        std::vector<unsigned char>(char2int(chunks[chunkindex].length, 0));

    for (int i = 0; i < 4; i++) {
      chunks[chunkindex].type[i] = data[index++];
    }

    if (char2int(chunks[chunkindex].length, 0) != 0) {
      for (int i = 0; i < char2int(chunks[chunkindex].length, 0); i++) {
        chunks[chunkindex].data[i] = data[index++];
      }
    }

    for (int i = 0; i < 4; i++) {
      chunks[chunkindex].CRC[i] = data[index++];
    }

    chunkindex++;
  }

  for (int i = 0; i < chunkindex; i++) {
    char name[5];
    for (int j = 0; j < 4; j++) {
      name[j] = chunks[i].type[j];
    }
    name[4] = '\0';

    if (strcmp(name, "IHDR") == 0) {
      std::cout << "FOUND IHDR" << std::endl;
      width = char2int(&(chunks[i].data[0]), 0);
      height = char2int(&(chunks[i].data[0]), 4);
      bitdepth = chunks[i].data[8];
      colourtype = chunks[i].data[9];
      compressionmethod = chunks[i].data[10];
      filtermethod = chunks[i].data[11];
      interlacemethod = chunks[i].data[12];

    } else if (strcmp(name, "PLTE") == 0) {
      std::cout << "FOUND PLTE" << std::endl;
    } else if (strcmp(name, "IDAT") == 0) {
      std::cout << "FOUND IDAT" << std::endl;
    } else if (strcmp(name, "IEND") == 0) {
      std::cout << "FOUND IEND" << std::endl;
    }
  }

  std::cout << "Width: " << width << std::endl;
  std::cout << "Height: " << height << std::endl;

  // delete[] chunks;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.