在读取DICOM文件时,在发布模式下ITK访问冲突错误但在调试模式下没有

时间:2013-02-19 02:03:25

标签: c++ memory access-violation itk

我知道很多人都有Release VS的这个问题。调试模式。我已经搜索了很多,并通过我的程序的堆栈跟踪和检查指针。但是,当我的程序在调试模式下完美运行时,我无法理解为什么在Release模式下会出现Access Violation错误!我看到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.感谢您的回答。

2 个答案:

答案 0 :(得分:4)

感谢Paolo的回答。我并行尝试了几件事,直到现在我找到了解决方案!我不能真正得到gflags来运行我的程序,但是因为我有一种直觉,认为问题不在代码中,所以我没有投入太多时间。

无论如何,这是我做的和已解决问题:

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

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

ITKCommon.dll is missing!

尽管我将visual studio中的所有文件夹和所有设置设置为使用release文件夹,我的程序在运行时从调试文件夹中使用了ITKCommon.dll。所以我复制了ITKCommon.dll从发布版本构建到我的发布文件夹中,瞧!我的程序就像一个魅力。

答案 1 :(得分:0)

尝试使用gflags(在WinSDK的调试工具中可用)或appverifier(我认为它也在winsdk中)。

在您的应用程序上启用gflag时(在调试模式下),它会发现内存中发生的所有令人讨厌的事情,并在发生错误时立即提出断点