返回0后的段错误(Segfault)

4

我希望用ITK编写一个简单的色彩比例程序,但在主函数的return 0;后导致了段错误。 以下是我的代码。

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include <iostream>
#include <string>
#include <vector>
#include "itkRGBPixel.h"


const unsigned int  Dimension = 2;
typedef itk::RGBPixel< unsigned char >       PixelType;
typedef itk::Image< PixelType, Dimension >   ImageType;
typedef itk::ImageFileReader< ImageType >    ReaderType;
typedef itk::ImageFileWriter< ImageType >   WriterType;

int main(int argc, char** argv)
{   
std::string input=argv[1], output=argv[2];

//allocation of the image data
ReaderType::Pointer reader    = ReaderType::New();
WriterType::Pointer writer = WriterType::New();

reader->SetFileName(input);
writer->SetFileName(output);

reader->Update(); 

//access image
ImageType::Pointer image = reader->GetOutput();
ImageType::Pointer output_img;

 //apparently providing the spacing and origin in ITK is mandatory
ImageType::SpacingType spacing;
spacing[0] = 0.33;
spacing[1] = 0.33;
image->SetSpacing(spacing);

ImageType::PointType origin;
origin[0] = 0.0;
origin[1] = 0.0;
image->SetOrigin(origin);

writer->SetInput( reader->GetOutput() ); 
    writer->Update(); 

 return EXIT_SUCCESS;
}

代码编译和链接时没有出现任何错误信息,但是在执行过程中出现了段错误。

通过使用gdb逐行执行程序,我将段错误指向了程序的最后一行:即return 0;之后。

以下是回溯信息:

Program received signal SIGSEGV, Segmentation fault.
0xb79099bc in ?? () from /usr/lib/i386-linux-gnu/libstdc++.so.6
(gdb) bt
#0  0xb79099bc in ?? () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#1  0xb7909a4e in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
 #2  0x08065369 in main (argc=3, argv=0xbffff1b4) at /home/thibault/workspace/OU/MachineLearning/Project1/src/itkTry1.cpp:221
(gdb)

当使用valgrind进行检查时:

    ==16671== Memcheck, a memory error detector
    ==16671== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
    ==16671== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
    ==16671== Command: ./ColorRatio clouds2.jpeg coucou.jpeg --track-origins=yes
    ==16671== 
    ==16671== Conditional jump or move depends on uninitialised value(s)
    ==16671==    at 0x4B28DD8: inflateReset2 (in /lib/i386-linux-gnu/libz.so.1.2.3.4)
    ==16671==    by 0x4B28EC7: inflateInit2_ (in /lib/i386-linux-gnu/libz.so.1.2.3.4)
    ==16671==    by 0x4C87E58: ??? (in /usr/lib/libITKniftiio.so.3.20.1)
    ==16671== 
    ==16671== Conditional jump or move depends on uninitialised value(s)
    ==16671==    at 0x4B28DD8: inflateReset2 (in /lib/i386-linux-gnu/libz.so.1.2.3.4)
    ==16671==    by 0x4B28EC7: inflateInit2_ (in /lib/i386-linux-gnu/libz.so.1.2.3.4)
    ==16671== 
    ==16671== Invalid read of size 4
    ==16671==    at 0x47429BC: ??? (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
    ==16671==    by 0x47CE4D2: (below main) (libc-start.c:226)
    ==16671==  Address 0xfffffffc is not stack'd, malloc'd or (recently) free'd
    ==16671== 
    ==16671== 
    ==16671== Process terminating with default action of signal 11 (SIGSEGV)
    ==16671==  Access not within mapped region at address 0xFFFFFFFC
    ==16671==    at 0x47429BC: ??? (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
    ==16671==    by 0x47CE4D2: (below main) (libc-start.c:226)
    ==16671==  If you believe this happened as a result of a stack
    ==16671==  overflow in your program's main thread (unlikely but
    ==16671==  possible), you can try to increase the size of the
    ==16671==  main thread stack using the --main-stacksize= flag.
    ==16671==  The main thread stack size used in this run was 8388608.
    ==16671== 
    ==16671== HEAP SUMMARY:
    ==16671==     in use at exit: 2,352,658 bytes in 63,532 blocks
    ==16671==   total heap usage: 74,071 allocs, 10,539 frees, 14,082,941 bytes allocated
    ==16671== 
    ==16671== LEAK SUMMARY:
    ==16671==    definitely lost: 49 bytes in 2 blocks
    ==16671==    indirectly lost: 0 bytes in 0 blocks
    ==16671==      possibly lost: 1,309,540 bytes in 42,156 blocks
    ==16671==    still reachable: 1,043,069 bytes in 21,374 blocks
    ==16671==         suppressed: 0 bytes in 0 blocks
    ==16671== Rerun with --leak-check=full to see details of leaked memory
    ==16671== 
    ==16671== For counts of detected and suppressed errors, rerun with: -v
    ==16671== Use --track-origins=yes to see where uninitialised values come from
    ==16671== ERROR SUMMARY: 5 errors from 3 contexts (suppressed: 0 from 0)
    Segmentation fault (core dumped)

即使有36000个无用的try/catch语句,我在主程序之后仍然会遇到相同的分段错误。
有人能帮帮我吗?
提前致谢。

看起来你正在破坏堆栈。你能否发布一个SSCCE - Some programmer dude
2
另外,你不应该从 main 函数返回 -1。任何非零数字通常被认为是错误的,如果你想要确保的话,可以使用 EXIT_FAILURE 来返回。 - Some programmer dude
1
谢谢您的回复。我已将代码编辑为SSCCE格式。它足够简短,自包含且可以编译。基本上它所做的就是从文件中读取图像并直接将其重写到另一个文件中。除此之外没有其他操作(据我所知)。问题仍然存在。 - Titi
1
顺便说一下,这张图片是一个png格式的图片。 - Titi
致命错误:itkImage.h:没有此文件或目录 - Mooing Duck
1
我正在使用Itk库!除了提供整个构建或复制每个头文件/源文件的整个内容之外,没有可能制作一个SSCCE! - Titi
1个回答

1

这段代码对我有效:

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

#include "itkImage.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkRGBPixel.h"

int main(int argc, char** argv)
{
  std::string input = "/home/doriad/temp/test.png";
  std::string output= "output.png";

  const unsigned int  Dimension = 2;
  typedef itk::RGBPixel< unsigned char >       PixelType;
  typedef itk::Image< PixelType, Dimension >   ImageType;
  typedef itk::ImageFileReader< ImageType >    ReaderType;
  typedef itk::ImageFileWriter< ImageType >   WriterType;

  //allocation of the reader
  ReaderType::Pointer reader    = ReaderType::New();
  reader->SetFileName(input);
  reader->Update();

  //access image
  ImageType::Pointer image = reader->GetOutput();
//  ImageType::Pointer output_img;// This line does nothing

  //apparently providing the spacing and origin in ITK is mandatory
  // The spacing and origin are read from the file.
//  ImageType::SpacingType spacing;
//  spacing[0] = 0.33;
//  spacing[1] = 0.33;
//  image->SetSpacing(spacing);

//  ImageType::PointType origin;
//  origin[0] = 0.0;
//  origin[1] = 0.0;
//  image->SetOrigin(origin);

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(output);
  writer->SetInput( reader->GetOutput() );
  writer->Update();

 return EXIT_SUCCESS;
}

当然,您必须将“input”字符串更改为实际拥有的文件。


好的,谢谢。我猜错误可能来自于setSpacing或setOrigin。如果只使用itk进行非医学定向的图像处理,为什么必须使用它呢?无论如何,感谢您的帮助。问题已解决。 - Titi
如果您读取的是非医学文件(如普通png),则阅读器将按预期的间距(1)和原点(0)生成内容,除非文件另有说明。您已通过接受答案正确地关闭了问题。 - David Doria

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接