c++ - 读取 DICOM 文件时在 Release模式下出现 ITK 访问冲突错误,但在 Debug模式下不会出现 ITK 访问冲突错误

标签 c++ memory access-violation itk

好吧,我知道很多人都有 Release VS 的这个问题。 Debug模式。我进行了很多搜索,查看了程序的堆栈跟踪并检查了指针。但是,我不明白为什么我的程序在 Debug模式下运行完美,而在 Release模式下却出现访问冲突错误!在深入 ITK 代码的一些步骤之后,我突然看到一个函数导致访问冲突。我将首先展示我的代码,然后是导致此访问冲突的调用层次结构:

这是我的类型定义:

//typedef unsigned char PixelType;
const unsigned int dimention = 3;

//STD types
typedef std::vector<std::string> FileNamesContainer;
typedef std::vector<std::string> SeriesUIDContainer; 

//ITK Types
typedef itk::DICOMSeriesFileNames NamesGeneratorType;
typedef itk::Image <signed short, dimention> ImageType; //Defining Image Type
typedef itk::ImageSeriesReader<ImageType> ReaderType; //Defining the type of the image series reader

//GDCM Types
typedef itk::GDCMImageIO DICOMImageIOType;

这是我的功能:

ReaderType::Pointer itkReadDICOM::ReadImages(char *sourceFolderAddress, std::string &seriesUID)
{
    std::cout<<"- Getting file names in: "<<sourceFolderAddress<<std::endl;
    std::cout<<"- Series ID: "<<seriesUID<<std::endl;

    //Creating a pointer to an object of the reader type. ReaderType is defined on top as itk ImageSeriesReader
    ReaderType::Pointer reader = ReaderType::New();

    //Setting the IO type by creating a dicomIO object from the GDCMImageIO. This will make sure we read DICOM images.
    DICOMImageIOType::Pointer dicomIO = DICOMImageIOType::New();
    reader->SetImageIO(dicomIO);

    //Creating a dicom series name generator. It will generate the name of the dicom series based on the input directory.
    NamesGeneratorType::Pointer namesGenerator = NamesGeneratorType::New();
    namesGenerator->SetDirectory(sourceFolderAddress);

    //Getting names and passing the names to the reader to read them.
    FileNamesContainer fileNames = namesGenerator->GetFileNames(seriesUID);
    reader->SetFileNames(fileNames);

    std::cout<<"- Reading files ... ";

    //Adding a reading progress observer to the reader so we can see how are we reading.
    ITKCmdProgressObserver::Pointer progressObserver = ITKCmdProgressObserver::New();
    reader->AddObserver(itk::ProgressEvent(), progressObserver);

    //Actually reading the files here. If any error happens it will be Printed and the program exists. 
    try
    {
        reader->UpdateLargestPossibleRegion();
        std::cout<<"Successfully read "<< fileNames.size() <<" file(s)."<<std::endl;
    }
    catch  (itk::ExceptionObject &ex)
    {
        std::cout<<"Failed."<<std::endl<<"*********************************************************************"<<std::endl;
        std::cout<<ex<<std::endl;
        std::cout<<"*********************************************************************"<<std::endl;
        return 0;
    }
    return reader;
}

导致错误的调用是这样的:

reader->UpdateLargestPossibleRegion();

上面的函数调用经历了最终导致错误的调用链:

1.

this->UpdateOutputInformation(); //void ProcessObject::UpdateLargestPossibleRegion()

2.

this->GenerateOutputInformation(); //void ProcessObject::Update()

3.

reader->UpdateOutputInformation(); //template <class TOutputImage> void ImageSeriesReader<TOutputImage>::GenerateOutputInformation(void)

4.

this->GenerateOutputInformation(); //void ProcessObject::UpdateOutputInformation()

5.

m_ImageIO->SetFileName(m_FileName.c_str());
m_ImageIO->ReadImageInformation(); //template <class TOutputImage, class ConvertPixelTraits> void ImageFileReader<TOutputImage, ConvertPixelTraits> ::GenerateOutputInformation(void)

在第 5 步中,第一行没有问题,第二行导致访问冲突。它甚至不让我通过它。我正在使用 Visual Studio 2010。感谢您的回答。

最佳答案

感谢保罗的回答。我同时尝试了几件事,直到现在我找到了解决方案!虽然我无法真正让 gflags 运行我的程序,但由于我有直觉,问题不在代码中,所以我没有在它上面投入太多时间。

无论如何,这就是我所做的并且解决了问题:

我从 ITK 网站下载了一个名为 resampleDICOM 的示例并对其进行了编译,但遇到了完全相同的问题。所以最初我认为这是一个 ITK 错误。然后我使用调试 (RelWithDebInfo) 在 Release模式下重新编译 ITK,这样我就可以在 Release模式下调试时进入 ITK 代码。令我惊讶的是,一个与 GDCMImageIO::MetaDataDictionary 相关的完全有效的指针突然变成了一个错误的指针 (),而没有任何代码影响它。所以我意识到某处应该存在堆损坏!我也知道导致这种损坏的原因不能在我的代码中。

所以我在很多线程中读到,混合调试和发布 .lib 和 .dll 文件会使事情变得非常糟糕。但我确定我使用的是 ITK 发布的 .lib 文件和 .dll 文件,因为我检查了很多次!我的意思是 MAAANY 次!我正要从阳台上跳下来结束这种痛苦,我有这个想法只是为了确保我的程序没有使用 ITK 调试编译中的任何内容。 所以我将 ITK 调试文件夹的名称更改为其他名称并在 Release模式下运行我的程序,突然:

ITKCommon.dll is missing!

尽管我将 visual studio 中的所有文件夹和所有设置设置为使用发布文件夹,我的程序在运行时使用调试文件夹中的 ITKCommon.dll。所以我复制了ITKCommon.dll 从发布构建到我的发布文件夹中,瞧!我的程序非常有效。

关于c++ - 读取 DICOM 文件时在 Release模式下出现 ITK 访问冲突错误,但在 Debug模式下不会出现 ITK 访问冲突错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14948611/

相关文章:

c++ - 在类的不同实例中共享的字符串变量

c - 这段代码有什么作用?内存分配

javascript - 如何获取 JavaScript 对象的大小?

c - C 结构的数据对齐

c++ - 使用变量地址读取另一个进程的内存

c++ - goto 对 C++ 编译器优化的影响

c++ - 如何确保仅在 C++ 中提供时才使用特定的类功能?

c++ - 使用 C++ OOB 的贪吃蛇游戏

c++ - 当线程/进程处于 sleep 状态时, sleep 线程或进程的指令是否继续执行?

C++ OpenGL glTexImage2D 访问冲突