4

Linuxで実行されているQTベースのシングルスレッドコンソールアプリは、Boostを使用してJSON文字列を解析し、JSONの非常に大きなチャンクを受信する場合を除いて、通常は正常に機能します。サイズが約160kb(!)の有効なJSONがあり、それを解析しようとすると、BoostのJSONパーサーの呼び出しが返されません。かなりの時間を残しました。その後、デバッガーの使用に割り込むと、何も起こらなかったかのように、アプリはメッセージループにアイドル状態で座っています。呼び出しは例外をスローしません。JSONはサイズが大きいことを除けば、特筆すべきことは何もありません。整形式で、完全にASCII文字で構成されています。

実行を単純に「あきらめて」QTメッセージループに戻すにはどうすればよいでしょうか。

void IncomingRequestHandler::OnRequest(const QString& message)
{
    try
    {
        std::stringstream ss;
        ss << message.toStdString();
        boost::property_tree::ptree requestObject;

        cout << "Before read_json" << endl;  // Gets here
        boost::property_tree::json_parser::read_json(ss, requestObject);
        cout << "After read_json" << endl;  // Never gets here

        // ... Some other code ...
    }
    catch (const boost::property_tree::json_parser::json_parser_error& e)
    {
        cout << "Invalid JSON" << endl;  // Never gets here
    }
    catch (const std::runtime_error& e)
    {
        cout << "Invalid JSON" << endl;  // Never gets here
    }
    catch (...)
    {
        cout << "Invalid JSON" << endl;  // Never gets here
    }
}
4

1 に答える 1

2

まず、上記の2つのコメントに同意します。プログラムを最小限に抑えるようにしてください。

次に、Qt(stl、boost、この特定のバージョンのバージョン)がこれほど大きな文字列を処理できるかどうかを確認します。パーサーが文字列全体を取得していることを確認してください。

第三に、私はsstreamではなくostringstreamを使用します。:)

Boostのドキュメントによると、パーサーがエラーを返す唯一の方法は、property_treeにエラー情報を返すことであるようです。永久に読み取りを続ける場合は、実際のJSONデータを超えてガベージを読み取っていて、スタックしていることを意味している可能性があります。

最後に、read_jsonはファイル名を受け入れることができるので、なぜファイルの読み取りとストリームの作成に煩わされるのでしょうか。これを試してみませんか:

    boost::property_tree::ptree requestObject;
    cout << "Before read_json" << endl;  // Gets here
    boost::property_tree::json_parser::read_json(jsonFileName.toStdString(),
                                                 requestObject);
    cout << "After read_json" << endl;  // Never gets here

大きなJSONファイル400Kbで少しテストを実行したところ、問題なく動作します。

    #include <iostream> 
    #include <string> 
    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/json_parser.hpp>

    using namespace std;

    int main(int argc, char* argv[])
    {
        string infname = argv[1];

        boost::property_tree::ptree requestObject;
        cout << "Before read_json" << endl;  // Gets here
        boost::property_tree::json_parser::read_json(infname, requestObject);
        cout << "After read_json" << endl;  // Works fine

        return 0;
    }
于 2012-06-23T21:05:50.303 に答える