[C++] 351 BBS閲覧アプリの製作 その32 掲示板クリック時に落ちる / クラッシュレポートの閲覧

[Mac M2 Pro 12CPU, MacOS Ventura 13.6, clang 15.0.0]

昨晩、自製BBS閲覧アプリで特定の掲示板をクリックするとアプリが落ちるようになってしまいました。

クラッシュレポートからXPath式を評価する際にエラーになることが判明しました。エラーになってもアプリが落ちないようにexecuteXpath関数の戻り値をNULL以外に変えるなど対処しましたが、結局うまくいきませんでした。

今朝になって正常動作するようになったものの、再発が懸念されます。クラッシュレポートは後からでもmacOSのコンソールアプリから閲覧できます。一応、エラーが発生しそうな箇所を修正して予防対策しておきました。戻り値云々は見当違いのようです。

当時の他の類似アプリでの挙動は確認できていませんが、ちょっとしたトラブルでもアプリが絶対に落ちないよう堅牢性を持たせたいものです。

// XPath式で要素を取得
xmlNodeSetPtr executeXpath(xmlDocPtr &doc, xmlChar *xpath_expr) {
    xmlXPathContextPtr xpath_context;
    xmlXPathObjectPtr  xpath_obj;

    xpath_context = xmlXPathNewContext(doc);
    if (xpath_context == NULL) {
        cerr << "Error: unable to create new XPath context" << endl;
        xmlFreeDoc(doc);
        return NULL;
    }
    xmlNodePtr node = xmlDocGetRootElement(doc);

    // XPath式を評価
    // 23/10/16 エラー発生, 23/10/17 回復
    xpath_obj = xmlXPathEvalExpression(xpath_expr, xpath_context);
    if (xmlXPathNodeSetIsEmpty(xpath_obj->nodesetval)) {
        cerr << "Error: unable to evaluate xpath expression" << endl;
        xmlXPathFreeContext(xpath_context);
        xmlFreeDoc(doc);
        return NULL;
    }

    return xpath_obj->nodesetval;
}
    xmlDoc* doc = htmlReadMemory(htmlBuffer.c_str(), htmlBuffer.size(), nullptr, nullptr, HTML_PARSE_RECOVER);
    if (doc) {
        xmlNodeSetPtr tradObj = executeXpath(doc, (xmlChar *)"//*[name()='small']/*[name()='a']");

        if (tradObj) {
            for (int i = 0; i < tradObj->nodeNr; i++) {
                xmlNodePtr node = tradObj->nodeTab[i];
                xmlChar* id0 = xmlGetProp(node, (xmlChar*)"href");
                xmlChar* title0 = xmlNodeGetContent(node);

                string id = convertToString(id0);
                id.erase(id.size() - 4);
                string title = convertToString(title0);
                // cout << "title: " << title << endl;

                idTitle.push_back(std::make_pair(id, title));
                
                xmlFree(id0);
                xmlFree(title0);
            }
        } else {
            return {}; // else部分がなかったので追記 23/10/17
        }
        xmlFreeDoc(doc);
    } else {
        return {}; // else部分がなかったので追記 23/10/17
    }
クラッシュレポートは後からでもコンソールアプリで確認可能
(保存期間は不明)