2017-05-13 66 views
0

我使用Visual Studio 17 v15.0和Win 10 Anniversary Update SDK。cppwinrt示例中的神祕崩潰

我使用cl /EHsc /O2 /DUNICODE /bigobj /await /std:c++latest/MTMD構建以下代碼(基本上爲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崩潰,您是否嘗試在您的代碼中打印語句,以找到發生崩潰的位置? –

+0

我用/ MT和/ MTd編譯並用vscode進行調試,按照建議在printf處設置斷點,繼續進入,但是最終出現在符號中,這是祕密的VC++內部源代碼。總是像GDB一樣正常退出。任何想法? –

+0

@AlgirdasPreidžius我想我找到了根本原因,請參閱下面的答案。 –

回答

0

原來由AsyncSample().get()返回hstring不是空終止,所以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'始終爲零終止。而'winrt :: hstring'只是'HSTRING'的一個包裝,沒有理由相信它會違反這些規則。你是如何驗證的,返回的值不是零終止的? – IInspectable