1

多くの人が 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;

これが私の機能です:

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 では、最初の行は問題なく、2 行目でアクセス違反が発生します。一歩踏み出すことすらできません。Visual Studio 2010 を使用しています。ご回答ありがとうございます。

4

2 に答える 2

4

答えてくれてありがとうパオロ。私は今までいくつかのことを並行して試しましたが、解決策を見つけました!プログラムを実行するためにgflagsを実際に取得することはできませんでしたが、問題は実際にはコードにないという直感を持っていたので、あまり時間をかけませんでした。

とにかくここに私がしたことと問題を解決したことがあります:

ITK WebサイトからresampleDICOMというサンプルをダウンロードしてコンパイルしましたが、まったく同じ問題が発生しました。ですから、最初はITKのバグだと思いました。次に、デバッグ(RelWithDebInfo)を使用してリリースモードでITKを再コンパイルしたので、リリースモードでデバッグしながらITKコードに入ることができます。驚いたことに、GDCMImageIO :: MetaDataDictionaryに関連する完全に有効なポインターが、コードに影響を与えることなく、突然不正なポインター()に変わっていました。だから私はどこかにヒープの破損があるはずだと気づきました!また、この破損の原因がコードに含まれていないこともわかっていました。

だから私は非常に多くのスレッドを読んだので、デバッグとリリースの.libファイルと.dllファイルを混ぜると物事が本当に厄介になる可能性があります。しかし、何度もチェックしたので、ITKリリースの.libファイルと.dllファイルを使用していると確信していました。そして私はMAAANY回を意味します!私はバルコニーから飛び降りて、ITKのデバッグコンパイルでプログラムによって何も使用されていないことを確認するためだけにこのアイデアを持っていたというこの悲惨さを終わらせようとしていました。そこで、ITKデバッグフォルダの名前を別の名前に変更し、プログラムをリリースモードで実行すると、突然次のようになりました。

ITKCommon.dll is missing!

Visual Studioのすべてのフォルダーとすべての設定をリリースフォルダーを使用するように設定したにもかかわらず、プログラムは実行時にデバッグフォルダーからITKCommon.dllを使用していました。そこで、ITKCommon.dllをリリースビルドからリリースフォルダにコピーして、出来上がりました。私のプログラムは魅力のように機能しました。

于 2013-02-19T21:35:17.403 に答える
0

gflags (WinSDK のデバッグ ツールで利用可能) または appverifier (winsdk にもあると思います) を使用してみてください。

アプリで (デバッグ モードで) gflag を有効にすると、メモリで発生するすべての厄介なことが検出され、問題が発生するとすぐにブレークポイントが発生します。

于 2013-02-19T14:09:50.870 に答える