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

Posted

技术标签:

【中文标题】从二进制文件加载图像像素时出现 C++ 分段错误【英文标题】:C++ Segmentation Fault when loading Image Pixels from Binary File 【发布时间】:2017-08-03 19:12:33 【问题描述】:

为了好玩而做一些 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 );
;

【问题讨论】:

什么是pixels 我认为这可能是在您的写入函数中保存。当您使用 char* 时,可能只允许读取操作。这是我的第一个猜测。你能测试一下 save 方法,看看你是否遇到了段错误? 您为什么不使用调试器准确检查它发生的位置?另外,顺便说一下,行、列和像素是什么?为什么它们显然是全球性的? Why is iostream::eof inside a loop condition considered wrong?. @EastonBornmeier,保存功能正常,只是加载功能不正常 【参考方案1】:

当您使用 ios::ate 打开文件时,您将文件指针移动到文件末尾,然后再尝试读取它。您想从文件的开头读取,因此应删除 ios::ate。

另外,您是在循环中阅读,而不是在循环中写入。你的 while 应该是一个 if,或者只是被删除。

也读取不会调整您的指针(或者不应该......看我的下一点),而只是将数据读入您指向的位置。所以 NULL 检查(如果像素==NULL)是无意义的。

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

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;
  ...

【讨论】:

所以对于读取功能,它应该读取类似这样的内容inFile.read(reinterpret_cast&lt;char*&gt;(&amp;cols), sizeof(unsigned int));inFile.read(reinterpret_cast&lt;char*&gt;(&amp;rows), sizeof(unsigned int));inFile.read(reinterpret_cast&lt;char*&gt;(pixels), sizeof(uint8_t) * cols * rows); 为了保存 inFile.read(reinterpret_cast&lt;char*&gt;(pixels), sizeof(uint8_t) * cols * rows); 但它给了我 free():invalid size 可能需要看main()。您需要为像素指针分配内存。理想情况下,正确的数量,如下所示:“pixels = new uint8_t[cols * rows];” 为此:if (pixels != NULL) delete [] pixels; 这个应该放在哪里? 我在回答中澄清了【参考方案2】:

除了@zzxyz 的回答之外,您可能还遇到了字节顺序 的问题。当您阅读colsrows 时,c++ 可能会将整数中的字节从最低有效位到最高位(小端)排序,而文件可以将字节从最高位到最低位(大端)排序,例如(查看更多here)。这可能会为您提供colsrows 的值,这与您的预期大相径庭,读取cols * rows 字节可能会使inFile 尝试读取远远超出文件长度的内容。我建议检查或打印colsrows 的值,并确保它们符合您的期望;如果不是,则必须颠倒整数中字节的顺序。

【讨论】:

以上是关于从二进制文件加载图像像素时出现 C++ 分段错误的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中修改 cv::Mat 数据时出现分段错误

创建多个矩阵时出现分段错误(核心转储)

添加向量时出现分段错误。 (C++)

C++ 分段错误 OpenCV

在 C++ 中比较来自向量的字符串时出现分段错误

在 C++ 索引程序中使用向量时出现分段错误 11