Aracılığıyla paylaş


C++'da Özel Durumlar ve Yığını Geriye Doğru İzleme

C++ özel durum mekanizmasında denetim, throw deyiminden throw türünü işleyebilen ilk catch deyimine geçer. Catch deyimine ulaşıldığında, throw ve catch deyimleri arasındaki kapsamdaki tüm otomatik değişkenler yığın geri sarma olarak bilinen bir işlemde yok edilir. Yığın geriye doğru izleme işleminde, yürütme aşağıdaki gibi olur:

  1. Denetim, normal sıralı yürütme ile deyimine try ulaşır. Bloktaki try korunan bölüm yürütülür.

  2. Korunan bölümün yürütülmesi sırasında özel durum oluşturulursa, catch bloğu izleyen try yan tümceler yürütülür. Yürütme, ilişkili try bloğu izleyen son catch yan tümceden sonra deyiminde devam eder.

  3. Korunan bölümün yürütülmesi sırasında veya korunan bölümün doğrudan veya dolaylı olarak çağırdığı herhangi bir yordamda özel durum oluşursa, işlenen tarafından throw oluşturulan nesneden bir özel durum nesnesi oluşturulur. (Bu, bir kopya oluşturucus un dahil olabileceğini gösterir.) Bu noktada derleyici, daha yüksek bir catch yürütme bağlamında, oluşan türün özel durumunu işleyebilen veya herhangi bir özel durum türünü işleyebilen bir işleyici için bir catch yan tümce arar. İşleyiciler catch , blok sonrasındaki try görünümlerine göre incelenir. Uygun işleyici bulunamazsa, sonraki dinamik olarak kapsayan try blok incelenmiş olur. Bu işlem, en dıştaki kapalı blok incelenene try kadar devam eder.

  4. Eşleşen bir işleyici hala bulunamazsa ya da geriye doğru işlem sırasında işleyici denetimi almadan önce bir özel durum oluşursa, önceden tanımlanmış çalışma zamanı işlevi terminate çağrılır. Özel durum, geriye doğru izleme başlamadan önce ve bir özel durum oluştuktan sonra oluşursa, terminate çağrılır.

  5. Eşleşen catch bir işleyici bulunursa ve değere göre yakalarsa, özel durum nesnesi kopyalanarak resmi parametresi başlatılır. Başvuruya göre yakalarsa, parametre özel durum nesnesine başvurmak için başlatılır. Biçimsel parametre başlatıldıktan sonra, yığını geriye doğru izleme işlemi başlar. Bu, işleyiciyle ilişkili bloğun başlangıcı try ile catch özel durumun oluşturma sitesi arasında tamamen yapılandırılmış ancak henüz yok edilmeyen tüm otomatik nesnelerin yok edilmesini içerir. Yok etme işlemi oluşturma işleminin ters sırasıyla yapılır. İşleyici catch yürütülür ve program yürütmeyi son işleyiciden sonra sürdürür; diğer bir deyişle, işleyici catch olmayan ilk deyimde veya yapıda. Denetim bir işleyiciyi yalnızca bir deyimi veya deyimindeki switch bir goto etiket aracılığıyla değil, atılan bir case özel durum aracılığıyla girebilircatch.

Yığın geri sarmayı kaldırma örneği

Aşağıdaki örnekte bir özel durum oluştuğunda yığının nasıl kaldırıldığı gösterilmektedir. İş parçacığı üzerindeki yürütme, C içindeki throw deyiminden main içindeki catch deyimine atlar ve yol boyunca her işlevi geriye doğru alır. Dummy nesnelerinin oluşturulduğu ve ardından kapsam dışına çıkarken yok edildikleri sıralamaya dikkat edin. Ayrıca, catch deyimini içeren main haricinde, hiçbir işlevin tamamlamadığına dikkat edin. A işlevi B() için yaptığı çağrıdan, B işlevi de C() için yaptığı çağrıdan hiçbir zaman dönmez. Dummy işaretçisine ve ilişkili delete deyiminin tanımına ilişkin açıklamayı kaldırır ve ardından programı çalıştırırsanız, işaretçinin asla silinmediğine dikkat edin. Bu, işlevler özel durum sağlamadığında neler olabileceğini gösterir. Daha fazla bilgi için bkz . Nasıl yapılır: Özel Durumlar için Tasarım. Catch deyimi için açıklama satırı yaparsanız, işlenmemiş bir özel durum nedeniyle bir program sonlandığında ne olacağını görebilirsiniz.

#include <string>
#include <iostream>
using namespace std;

class MyException{};
class Dummy
{
    public:
    Dummy(string s) : MyName(s) { PrintMsg("Created Dummy:"); }
    Dummy(const Dummy& other) : MyName(other.MyName){ PrintMsg("Copy created Dummy:"); }
    ~Dummy(){ PrintMsg("Destroyed Dummy:"); }
    void PrintMsg(string s) { cout << s  << MyName <<  endl; }
    string MyName;
    int level;
};

void C(Dummy d, int i)
{
    cout << "Entering FunctionC" << endl;
    d.MyName = " C";
    throw MyException();

    cout << "Exiting FunctionC" << endl;
}

void B(Dummy d, int i)
{
    cout << "Entering FunctionB" << endl;
    d.MyName = "B";
    C(d, i + 1);
    cout << "Exiting FunctionB" << endl;
}

void A(Dummy d, int i)
{
    cout << "Entering FunctionA" << endl;
    d.MyName = " A" ;
  //  Dummy* pd = new Dummy("new Dummy"); //Not exception safe!!!
    B(d, i + 1);
 //   delete pd;
    cout << "Exiting FunctionA" << endl;
}

int main()
{
    cout << "Entering main" << endl;
    try
    {
        Dummy d(" M");
        A(d,1);
    }
    catch (MyException& e)
    {
        cout << "Caught an exception of type: " << typeid(e).name() << endl;
    }

    cout << "Exiting main." << endl;
    char c;
    cin >> c;
}

/* Output:
    Entering main
    Created Dummy: M
    Copy created Dummy: M
    Entering FunctionA
    Copy created Dummy: A
    Entering FunctionB
    Copy created Dummy: B
    Entering FunctionC
    Destroyed Dummy: C
    Destroyed Dummy: B
    Destroyed Dummy: A
    Destroyed Dummy: M
    Caught an exception of type: class MyException
    Exiting main.

*/