从二进制文件加载图像像素时的C ++分段错误

时间:2017-08-03 19:12:33

标签: c++ file-io segmentation-fault

为了好玩而做一些C ++并且遇到一个问题,当我在对图像进行一些修改后加载图像时,它会给我分段错误。我觉得我错过了什么,但我不知道在哪里。

编辑以下是保存和加载功能的代码,(假设包含所有必需的头文件):

    int Image::save(const char* filename)
    {
      if(filename == NULL)
      {
        return 1;
      }
      ///*
      ofstream outFile(filename, ios::out | ios::binary);
      if (!outFile)
      {
        return 1;
      }
      outFile.write(reinterpret_cast<char*>(&cols), sizeof(unsigned int));
      outFile.write(reinterpret_cast<char*>(&rows), sizeof(unsigned int));
      outFile.write(reinterpret_cast<char*>(pixels), sizeof(uint8_t) * cols * rows);
      outFile.close();
      return 0;
    }

    int Image::load(const char* filename)
    {
      if(filename == NULL)
      {
        return 1;
      }
      ///*
      ifstream inFile(filename, ios::in | ios::binary);
      if (!inFile)
      {
        return 1;
      }
      **//feels like the segmentation fault is happening here**

      inFile.read(reinterpret_cast<char*>(&cols), sizeof(unsigned int));
      inFile.read(reinterpret_cast<char*>(&rows), sizeof(unsigned int));
      inFile.read(reinterpret_cast<char*>(pixels), sizeof(uint8_t) * cols * rows);
      inFile.close();
      return 0;
    }

修改 这是我正在使用的头文件:

class Image {

public:
  unsigned int cols;
  unsigned int rows;
  uint8_t* pixels;

...

/* Saves the image in the file filename. In a format that can be
     loaded by load().  Returns 0 on success, else a non-zero error
     code. */
  int save( const char* filename );

  /* Load an image from the file filename, replacing the current
     image size and data. The file is in a format that was saved by
     save().  Returns 0 success, else a non-zero error code . */
  int load( const char* filename );
};

2 个答案:

答案 0 :(得分:2)

您在使用ios :: ate打开文件时,尝试将文件指针移动到文件末尾。你想从文件的开头读取,所以应该删除ios :: ate。

此外,您正在循环阅读,而不是在循环中写入。你的时间应该是if,或者只是删除。

同时读取不会调整指针(或者不应该......看下一点),而只是将数据读入您指向的位置。因此NULL检查(如果pixels == NULL)是无意义的。

此外,您不应该使用pixels的地址运算符(&amp;)。 pixels已经是一个指针,您对此变量的读取和写入都应删除&,如下所示:

inFile.read(reinterpret_cast<char*>(pixels), sizeof(uint8_t) * cols * rows);

您可能会发现这有用: http://boredzo.org/pointers/

编辑:

    inFile.read(reinterpret_cast<char*>(&cols), sizeof(unsigned int));
    inFile.read(reinterpret_cast<char*>(&rows), sizeof(unsigned int));
    resize(cols, rows, 0);
    inFile.read(reinterpret_cast<char*>(pixels), sizeof(uint8_t) * cols * rows);

你的resize()需要确保指针在尝试删除之前不是NULL,你可能应该将fill()作为一个单独的函数。

但至少要做到

int Image::resize(unsigned int width,  unsigned int height, uint8_t fillcolor)
{
  if (pixels != NULL)
      delete[] pixels;
  ...

答案 1 :(得分:1)

除了@ zzxyz的答案,您可能会遇到字节顺序的问题。当您阅读colsrows时,c ++可能会将整数中的字节排序为从最低有效到最高有效(小端),而文件可以将字节从最高有效位置排列到最低有效位置(大端) ,例如(参见更多here)。这可能会使colsrows的值与您期望的值大不相同,并且读取cols * rows个字节可能会使inFile尝试读取远远超出文件长度的值。我建议您检查或打印colsrows的值,并确保它们符合您的预期;如果没有,你将不得不颠倒整数中字节的顺序。