一千萬個為什麽

搜索

C ++可執行文件在運行時凍結

我編寫了一個簡單的控制臺程序,用於測試我正在構建的庫中的一些關鍵類。現在,代碼構建正確,沒有錯誤。但是,在執行代碼後,我發現應用程序在代碼中的某個點調用Index方法後停止工作。我嘗試調試幾種不同的方法來獲取有關問題的更多信息,但我收集的信息根本沒有幫助我。也許它會幫助那些知道我沒做什麽(或做錯了)的人。

這是Util命名空間的內容;

    template
class VectorNode
{
    public:
    VectorNode(var value, VectorNode* next = NULL, VectorNode* prev = NULL)
    {
        data = value;
        t_next = next;
        t_prev = prev;
    }
    ~VectorNode()
    {
        if (t_next != NULL)
            delete t_next;
    }


    virtual VectorNode* Next(){ return t_next; }//get the next node in line
    virtual void Next(VectorNode* newNode){ t_next = newNode; }//set the next node in line

    virtual VectorNode* Prev(){ return t_prev; }// get the previous node in line
    virtual void Prev(VectorNode* newNode){ t_prev = newNode; }//set the previous node in line

    virtual var Value(){ return data; }//get the node's value

    private:
    var data;
    VectorNode* t_next;
    VectorNode* t_prev;
};

template
class Vector
{
    public:
    Vector()
    {
        tailNode = new VectorNode(*(new var));
        headNode = new VectorNode(*(new var), tailNode);
        tailNode->Prev(headNode);
        size = new int;
        *size = 0;
    }
    ~Vector()
    {
        delete headNode;
        delete size;
    }


    int Size(){ return *size; }//get the size of a vector
    void Add(var toAdd, int index = 0)//
    {
        VectorNode* lastNode;
        if (index > (*size))
            index = *size;
        if (index < 1)//add to the end of the vector
        {
            lastNode = tailNode;
        }
        else
        {
            int i;
            if (index <= (*size/2))//if the index is less than half the size, iterate forwards
            {
                lastNode = headNode;
                for (i = 1; i <= index; i++){ lastNode = lastNode->Next(); }
            }
            else//otherwise, iterate backwards
            {
                lastNode = tailNode;
                for (i = *size; i >= index; i--){ lastNode = lastNode->Prev(); }
            }
        }
        VectorNode* temp = lastNode->Prev();
        VectorNode* newNode = new VectorNode(toAdd, lastNode, temp);
        lastNode->Prev(newNode);
        temp->Next(newNode);
        *size = *size + 1;
    }
    void Remove(int index)//remove an index
    {
        VectorNode* toRemove;
        VectorNode* lastNode;
        int i;
        if ((index > *size) || (index < 1))//if not in the domain...
            index = *size;
        if (index <= (*size/2))//iterate forwards
        {
            lastNode = headNode;
            for (i = 1; i < index+2; i++){ lastNode = lastNode->Next(); }
        }
        else//iterate backwards
        {
            lastNode = tailNode;
            for (i = *size; i > index; i--){ lastNode = lastNode->Prev(); }
        }
        toRemove = lastNode->Prev();
        VectorNode* temp = toRemove->Prev();
        temp->Next(lastNode);
        lastNode->Prev(temp);
        delete toRemove;
        *size = *size - 1;
    }
    var Index(int index)//get the value of a node
    {
        VectorNode* lastNode;
        int i;
        if (index <= (*size/2))//iterate forwards
        {
            lastNode = headNode;
            for (i = 1; i <= index; i++){ lastNode = lastNode->Next(); }
        }
        else//iterate backwards
        {
            lastNode = tailNode;
            for (i = *size; i >= index; i--){ lastNode = lastNode->Prev();}
        }
        return lastNode->Value();
    }

    private:
    int* size;
    VectorNode* tailNode;//the head and tail nodes are placeholders, to keep the list inside its boundaries
    VectorNode* headNode;
};

如果您不想閱讀,我會用評論標記每個方法,解釋其總體目的。另外,我嘗試添加一些代碼塊的小解釋。

而且,這是入口函數和包含;

#include "iostream"

#include "stdlib.h"//this has nothing in it that's being used

#include "testhead.h"//the location of the Util namespace

int main() { 使用命名空間Util;
Vector* x = new Vector();
x->Add(42);
x->Add(24);
x->Add(12);
x->Add(21);
std::cout << "Listing Indices\n";
for (int i = 1; i <= x->Size(); i++)
{
    std::cout << i << "\t" << x->Index(i) << "\n";
}
std::cout << "Size(pre-removal):\t" << x->Size() << "\n";
x->Remove(2);
std::cout << "Size(post-removal):\t" << x->Size() << "\n";
std::cout << "Listing Indices\n";
std::cout << 3 << "\t" << x->Index(3) << "\n";
for (int i = 1; i <= x->Size(); i++)
{
    std::cout << i << "\t" << x->Index(i) << "\n";
}
system("Pause");

}

好的,結果我得到了這個。在使用Remove方法之前,可以從Vector類中自由訪問任何索引。但是,在使用remove方法之後,無論刪除哪個索引,都不能訪問上面的索引。除非在我們刪除第一個索引的情況下,否則不能訪問索引。我嘗試單步執行代碼,但它使我在索引方法中使用了這行代碼;

else
{
lastNode = tailNode;
for (i = *size; i >= index; i--){ lastNode = lastNode->Prev();}//error occurs after running this line
}

現在,因為我能夠找出導致問題的Remove方法,所以我回過頭來得到一些關於它的輸出。我讓它在完成執行之前運行以下行,兩次。刪除前刪除一次,刪除後再刪除一次。

std::cout << (lastNode->Prev() == temp) << "\t" << (temp->Next() == lastNode) << "\n";

在刪除之前,它會打印1次,表明比較結果為真。但是,我第二次調用Prev和Next方法,程序凍結。我知道這是因為我釋放了內存中的位置,但比較顯示從其他節點到我刪除的節點的任何引用都消失了。現在,我的具體問題是為什麽會造成這種情況,我該如何解決?我對在堆上管理內存有一點了解,但這並不完全看起來好像會導致程序出現任何問題。所以,我可以使用一個簡短的解釋,如果有人願意提供它,為什麽會發生這種情況。

如果有任何幫助,我正在使用Code :: Blocks IDE和GNU GCC編譯器。另外,請告訴我,如果我做錯了與我問我的方式有關。我不經常訪問Stack Overflow,我不在這裏提問。這是我所知道的回答問題的最佳地方。

最佳答案

VectorNode類的析構函數通過t_next指針刪除對象指針。在toRemove指針上調用delete意味著調用該VectorNode對象的析構函數,然後調用下一個,然後是下一個等等。

所以基本上,當你刪除toRemove時,你刪除toRemove以及之後的所有對象。這會導致tailNode的t_prev指向已經釋放的內存,然後嘗試在Index函數中解除引用這些指針,這不是一件好事。

轉載註明原文: C ++可執行文件在運行時凍結