RIM*_*IMA 1 c++ memory access-violation itk
我知道很多人都有这个 Release VS 的问题。调试模式。我进行了很多搜索并检查了程序的堆栈跟踪并检查了指针。但是,我不明白为什么我的程序在调试模式下运行良好,而在发布模式下却出现访问冲突错误!我在 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;
Run Code Online (Sandbox Code Playgroud)
这是我的功能:
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;
}
Run Code Online (Sandbox Code Playgroud)
导致错误的调用是这样的:
reader->UpdateLargestPossibleRegion();
Run Code Online (Sandbox Code Playgroud)
上面的函数调用经历了最终导致错误的调用链:
1.
this->UpdateOutputInformation(); //void ProcessObject::UpdateLargestPossibleRegion()
Run Code Online (Sandbox Code Playgroud)
2.
this->GenerateOutputInformation(); //void ProcessObject::Update()
Run Code Online (Sandbox Code Playgroud)
3.
reader->UpdateOutputInformation(); //template <class TOutputImage> void ImageSeriesReader<TOutputImage>::GenerateOutputInformation(void)
Run Code Online (Sandbox Code Playgroud)
4.
this->GenerateOutputInformation(); //void ProcessObject::UpdateOutputInformation()
Run Code Online (Sandbox Code Playgroud)
5.
m_ImageIO->SetFileName(m_FileName.c_str());
m_ImageIO->ReadImageInformation(); //template <class TOutputImage, class ConvertPixelTraits> void ImageFileReader<TOutputImage, ConvertPixelTraits> ::GenerateOutputInformation(void)
Run Code Online (Sandbox Code Playgroud)
在步骤 5 中,第一行正常,第二行导致访问冲突。它甚至不让我跨过它。我正在使用 Visual Studio 2010。感谢您的回答。
感谢保罗的回答。我并行尝试了几件事,直到现在我找到了解决方案!虽然我无法真正让 gflags 来运行我的程序,但由于我有一种直觉,问题并不真正出在代码中,所以我没有在上面投入太多时间。
无论如何,这就是我所做的并解决了问题:
我从 ITK 网站下载了一个名为 resampleDICOM 的示例并对其进行了编译,但遇到了完全相同的问题。所以一开始我以为这是一个ITK bug。然后我在发布模式下使用调试(RelWithDebInfo)重新编译了 ITK,这样我就可以在发布模式下调试时进入 ITK 代码。令我惊讶的是,与 GDCMImageIO::MetaDataDictionary 相关的完全有效的指针突然变成了坏指针 (),而没有任何代码影响它。所以我意识到某处应该存在堆损坏!我也知道导致这种损坏的任何原因都不可能出现在我的代码中。
因此,我在很多线程中读到,混合调试和发布 .lib 和 .dll 文件会使事情变得非常糟糕。但我确信我正在使用 ITK 版本的 .lib 文件和 .dll 文件,因为我检查了很多次!我的意思是MAANY次!我正准备从阳台上跳下来,结束这种痛苦,我有这个想法只是为了确保我的程序没有使用 ITK 的调试编译中的任何内容。所以我将 ITK 调试文件夹的名称更改为其他名称,并在发布模式下运行我的程序,突然:
ITKCommon.dll is missing!
Run Code Online (Sandbox Code Playgroud)
尽管我将 Visual Studio 中的所有文件夹和所有设置设置为使用发布文件夹,但我的程序在运行时使用调试文件夹中的 ITKCommon.dll。因此,我将 ITKCommon.dll 从发布版本复制到我的发布文件夹中,瞧!我的程序运行得非常顺利。