2017-05-13 14 views
0

私はVisual Studio 17 v15.0とWin 10 Anniversary Update SDKを使用しています。cppwinrtの不思議なクラッシュ例

私はまたはMDで、cl /EHsc /O2 /DUNICODE /bigobj /await /std:c++latestで次のコード(基本的にsample in github repo)を作成します。それはエラーなしでコンパイルされます。

`" message.png "が現在のディレクトリに存在しない場合、例外がスローされ、キャッチされ、printfで報告され、クラッシュせずに終了します。

`` message.png "が現在のディレクトリにあるのときに実行すると、" Hello World! "何らかの理由でクラッシュしないでください。

奇妙なことですが、GDBデバッガの中で実行すると、GDBはいつもプログラムが正常に終了すると(実際にはクラッシュは起こりません)。

GDB出力:

[New Thread 1364.0x2324] 
[New Thread 1364.0x624] 
[New Thread 1364.0x12cc] 
[New Thread 1364.0x58c] 
[New Thread 1364.0x1134] 
[New Thread 1364.0x10d8] 
[New Thread 1364.0x18a8] 
[New Thread 1364.0x1794] 
[New Thread 1364.0x20e8] 
[New Thread 1364.0x2204] 
[New Thread 1364.0x1030] 
[New Thread 1364.0x1474] 
Hello world! 
[Thread 1364.0x10d8 exited with code 0] 
[Thread 1364.0x624 exited with code 0] 
[Thread 1364.0x20e8 exited with code 0] 
[Thread 1364.0x1794 exited with code 0] 
[Thread 1364.0x18a8 exited with code 0] 
[Thread 1364.0x58c exited with code 0] 
[Thread 1364.0x1134 exited with code 0] 
[Thread 1364.0x12cc exited with code 0] 
[Thread 1364.0x8d0 exited with code 0] 
[Thread 1364.0x2324 exited with code 0] 
[Thread 1364.0x1b38 exited with code 0] 
[Thread 1364.0x2204 exited with code 0] 
[Thread 1364.0x1030 exited with code 0] 
[Thread 1364.0x1474 exited with code 0] 
[Inferior 1 (process 1364) exited normally] 

コード:

#pragma comment(lib, "windowsapp") 
#pragma comment(lib, "pathcch") 

#include <winrt/Windows.Storage.Streams.h> 
#include <winrt/Windows.Graphics.Imaging.h> 
#include <winrt/Windows.Media.Ocr.h> 
#include <winrt/Windows.Networking.Sockets.h> 

#include <pathcch.h> 

using namespace winrt; 
using namespace std::chrono; 

using namespace Windows::Foundation; 
using namespace Windows::Storage; 
using namespace Windows::Storage::Streams; 
using namespace Windows::Graphics::Imaging; 
using namespace Windows::Media::Ocr; 

hstring MessagePath() 
{ 
    wchar_t buffer[1024]{}; 
    GetCurrentDirectory(_countof(buffer), buffer); 
    check_hresult(PathCchAppendEx(buffer, _countof(buffer), L"message.png", PATHCCH_ALLOW_LONG_PATHS)); 
    return buffer; 
} 

IAsyncOperation<hstring> AsyncSample() 
{ 
    StorageFile file = co_await StorageFile::GetFileFromPathAsync(MessagePath()); 
    IRandomAccessStream stream = co_await file.OpenAsync(FileAccessMode::Read); 

    BitmapDecoder decoder = co_await BitmapDecoder::CreateAsync(stream); 
    SoftwareBitmap bitmap = co_await decoder.GetSoftwareBitmapAsync(); 

    OcrEngine engine = OcrEngine::TryCreateFromUserProfileLanguages(); 
    OcrResult result = co_await engine.RecognizeAsync(bitmap); 
    return result.Text(); 
} 

int main() 
{ 
    init_apartment(); 

    try 
    { 
     printf("%ls\n", AsyncSample().get().c_str()); 
    } 
    catch (hresult_error const & e) 
    { 
     printf("hresult_error: (0x%8X) %ls\n", e.code(), e.message().c_str()); 
    } 

    return 0; 
} 
+0

GDBが添付された状態でコードがクラッシュしない場合は、コードにprintステートメントを入れてクラッシュが発生した場所を見つけようとしましたか? –

+0

私は/ MTと/ MTdを使ってビルドし、vscodeでデバッグし、printfにブレークポイントを設定しておくと、ステップインしているが、シークレットVC++内部ソースコードのシンボルに終わる。常にGDBのように通常通り終了します。何か案が? –

+0

@AlgirdasPreidžius私は根本的な原因を見つけたと思う、以下の私の答えを参照してください。 –

答えて

0

AsyncSample().get()によって返さhstringは終了nullではないので、printfクラッシュが判明。

try 
{ 
    auto ans = AsyncSample().get(); 
    printf("[%u]: ", ans.size()); 
    auto s = ans.c_str(); 
    for (uint32_t i = 0; i < ans.size(); i++) { 
     printf("%lc", s[i]); 
    } 
    putchar('\n'); 
} 
+0

これは正確ではないかと思います。 'HSTRING'は常にゼロで終了します。 '' HSTRING'のラッパーだけである '' winrt :: hstring'は、それらのルールに違反すると信じる理由はほとんどありません。戻り値がゼロ終了していないことをどのように確認しましたか? – IInspectable