Search code examples
c++memoryaccess-violationitk

ITK access violation error in release mode but not in debug mode while reading DICOM files


Well I know many have this problem of Release VS. Debug mode. I have searched a lot and went through stack trace of my program and checked pointers. However, I cannot understand why do I get Access Violation error in Release mode while my program works perfectly in Debug mode! I saw after some steps deep in ITK code suddenly a function causes access violation. I will first present my code, then the calling hierarchy that causes this access violation:

Here are my type definitions:

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

Here is my function:

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

The call causing error is this:

reader->UpdateLargestPossibleRegion();

The above function call goes through this chain of calls that finally cause error:

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)

On step 5 the first line is fine and the second line causes access violation. It does not even let me step through it. I am using Visual Studio 2010. I appreciate your answers.


Solution

  • Thanks Paolo for your answer. I tried several things in parallel until now I found the solution! I couldn't really get gflags to run my program though but since I had a gut feeling that problem is not really in the code I didn't invest too much time on it.

    Anyways here is what I did and SOLVED the problem:

    I downloaded a sample from ITK website called resampleDICOM and compiled it and had the exact same problem. So initially I thought it is an ITK bug. Then I recompiled ITK in release mode with debug (RelWithDebInfo) so I can go into ITK code while debugging in release mode. To my surprise a completely valid pointer related to GDCMImageIO::MetaDataDictionary was suddenly turning to a bad pointer () without any code affecting it. So I realized there should be a heap corruption somewhere! I also knew whatever is causing this corruption cannot be in my code.

    So I read in so many threads that mixing Debug and Release .lib and .dll files can makes things really nasty. But I was sure that I am using ITK release .lib files and .dll files since I checked them many times! and I mean MAAANY times! I was about to jump down from balcony and put an end to this misery that I had this idea just to make sure that nothing in debug compilation of ITK is being used by my program. So I changed the name of ITK debug folder to something else and ran my program in release mode and suddenly:

    ITKCommon.dll is missing!
    

    Despite the fact that I set all the folders and all settings in visual studio to use the release folder, my program was using ITKCommon.dll at runtime from the debug folder. So I copied the the ITKCommon.dll from the release build into my release folder and voila! My program worked like a charm.