4

私はまだ新しいstlメンバーの初心者ですが、このコードがセグメンテーション違反を引き起こしている理由を誰かが指摘できますか?

#include<memory>
#include<stdio.h>
#include<map>
#include<set>
#include<string>
using namespace std;
struct StubClass
{
    weak_ptr<string> b;
    int c;
    friend bool operator==(StubClass x,StubClass y);
    friend bool operator<(StubClass x,StubClass y);
    StubClass(weak_ptr<string> x):b(x){c=5;}    
};
bool operator==(StubClass d,StubClass c) { return d.b==c.b;}
bool operator<(StubClass d,StubClass c) { return d.b<c.b; }


int main()
{
    shared_ptr<string> spPtr(new string("Hello"));
    weak_ptr<string> wpPtr(spPtr);
    StubClass hello(wpPtr);
    set<StubClass> helloSet;
    helloSet.insert(hello);
    if(helloSet.find(StubClass(wpPtr))!=helloSet.end()) printf("YAYA");
    else puts("Bye");
}

エラーは一列に並んでいます

if(helloSet.find(StubClass(wpPtr))!= helloSet.end())printf( "YAYA");

さらなる調査により、StubClassのコンパレータ関数が呼び出されたときに問題があることが明らかになりました。ここでプログラムをコンパイルしています

編集:

bool operator==(StubClass d,StubClass c) { return d.b.lock()==c.b.lock();}
bool operator<(StubClass d,StubClass c) { return d.b.lock()<c.b.lock(); }

これで問題は解決しました。もっと読む必要があります。:(とにかく、コミュニティの誰もが最初のコードがSIGSEGVを与える理由を説明できます。私は最終的にそれを理解しましたが、それでも良い説明は害にはなりません。:)

4

2 に答える 2

5

誤って無限再帰を設定したため、元のコードのセグメンテーション違反が発生しました。

bool operator<(StubClass d,StubClass c) { return d.b<c.b; }

operator<はありませんweak_ptrweak_ptrただし、 からへの暗黙的な変換がありますStubClass。を持っStubClassていoperator<ます。したがって、この関数は自分自身を無期限に呼び出します。したがって、セグメンテーション違反です。

現在inkoobooから受け入れられている回答も、未定義の動作につながり、おそらくクラッシュします。プログラムの実行中に有効期限が切れるとweak_ptrs(テスト ケースよりも複雑なもの)、それらの順序が変更されます。weak_ptrsの 2 つの間でこれが発生するとsetsetが破損し、クラッシュにつながる可能性があります。ただしowner_less、このユースケース用に特別に設計された方法を使用して、これを回避する方法があります。

bool operator==(const StubClass& d, const StubClass& c)
{
    return !owner_less<weak_ptr<string>>()(d.b, c.b) &&
           !owner_less<weak_ptr<string>>()(c.b, d.b);
}
bool operator<(const StubClass& d, const StubClass& c)
{
    return owner_less<weak_ptr<string>>()(d.b, c.b);
}

または、必要に応じて、メンバー関数を使用してコーディングすることもできますowner_before。どちらも同等です:

bool operator==(const StubClass& d, const StubClass& c)
{
    return !d.b.owner_before(c.b) && !c.b.owner_before(d.b);
}
bool operator<(const StubClass& d, const StubClass& c)
{
    return d.b.owner_before(c.b);
}

これらの関数を使用すると、一方weak_ptrが期限切れになり、もう一方が期限切れにならない場合でも、順序は安定したままです。したがって、明確に定義されsetた .

于 2012-06-14T15:27:20.943 に答える
4

weak_ptrに格納されている文字列を比較する場合は、次のようにします。

bool operator<(StubClass d, StubClass c) 
{
    std::shared_ptr<std::string> a = d.b.lock();
    std::shared_ptr<std::string> b = c.b.lock();

    if (!a && !b)
        return false; 

    if (!a)
        return true;

    if (!b)
        return false;

    return *a < *b;
}

実行結果

于 2012-06-14T14:07:22.787 に答える