2011-09-29 131 views
2

爲什麼我在這裏得到一個訪問衝突讀取位置0xC0000005,如果在我在linux中編碼時,相同的代碼就像一個魅力一樣?C++訪問違規?

if(nodo->izq!=NULL) //nodo is a class or struct and "sig" is a pointer of the same kind 
    VaciarAux(nodo->izq); 

有沒有辦法在沒有未處理的異常的情況下完成這個任務? 斷言會做的伎倆?

這裏是功能

void Arbol<T>::VaciarAux(Nodo<T> * &nodo) 
{ 
    if(nodo->izq!=NULL) 
     VaciarAux(nodo->izq); 
    if(nodo->der!=NULL) 
     VaciarAux(nodo->der); 
    if(nodo->izq == NULL && nodo->der ==NULL) 
    { 
     actual = nodo; 
     nodo=NULL; 
     delete actual; 
     contador--; 
    } 
+0

'assert'只是作爲您的程序的健全性檢查。任何使用'assert'完成的檢查都不應該存在於生產代碼中。你可能在某處讀取了未初始化的內存,因此你的NULL檢查通過了,但是隨後你進入了隨機存儲區。但是,您應該發佈更多代碼來幫助評估您的問題。 – Pablo

+0

沒有足夠的信息在您的問題需要足夠的答覆。訪問違規可能是出於任何原因。 –

+0

你是什麼意思「斷言會做詭計」?問問題時始終要非常具體。 –

回答

4

最有可能的,因爲nodo本身是無效的指針。 ->取消引用會導致問題。

您需要檢查可能影響該值的事情(導致損壞的緩衝區溢出,由於某種原因設置爲NULL)。

需要注意的是:

if (nodo->izq != NULL) 

檢查,如果nodo變量爲NULL,而是如果有什麼nodoizq成員爲NULL。

如果你只是想要做什麼,如果nodo本身是NULL,你可以把在開始:

if (nodo == NULL) return; 

,但我仍然認爲你會好得多回溯到問題的根源而不是僅僅修復一個症狀。


我認爲問題出在您處理樹的方式。你是切實做好:

def delTree (node): 
    if node.left != NULL: 
     delTree (node.left) 
    if node.right != NULL: 
     delTree (node.right) 
    if node.left == NULL and node.right == NULL: 
     delete node and whatever else you have to do 

與主要的問題是,delTree (node.left)意味着,如果樹是空的,你會得到你看到確切的問題,因爲你試圖做的第一件事就是廢棄的空根節點。

更通常的做法是先復發孩子無條件地(用NULL保護器),然後處理節點本身,是這樣的:

def delTree (node): 
    if node == NULL: 
     return 
    delTree (node.left) 
    delTree (node.right) 
    delete node and whatever else you have to do 

這將正確處理空樹,仍然正確刪除所有兒童在父母面前。它只是看起來更優雅,這是首先使用遞歸的原因之一:-)

我將它作爲一個練習,讓讀者把它變成C++。

+0

所以用一個空根初始化一棵樹是不好的做法? – HoNgOuRu

+0

不,這實際上是相當標準的 - 它是一棵空的樹。我想我現在看到了你的情況(儘管語言有困難) - 我會更新答案。 – paxdiablo

+0

如果(nodo-> izq!= NULL) 我需要在此行中返回false的真,那就是我決定沿着樹枝向左或向右的位置。 – HoNgOuRu

0

您可能想要了解如何創建Nodo類型(即查看其默認構造函數...應該有一個,因爲它是包含指針的類/結構)。例如,如果您未初始化Nodo類型的成員,以便每當創建一個Nodo對象時,這兩個指針成員初始爲NULL,則它們可以具有任何不確定的值,以便Arbol<T>::VaciarAux內的NULL值的測試將失敗。例如,一個新的Nodo最終會被初始化爲某個隨機值的指針,但包含在Nodo的指針成員中的那些隨機存儲器值不是在內存中可訪問的有效位置。然後,當您測試指針是否爲NULL時,測試結果爲false,並且您嘗試在下一次遞歸調用Arbol<T>::VaciarAux時解除引用它們,導致訪問衝突。

+0

endeed,我有一個NULL值初始化它們在默認的構造函數 – HoNgOuRu

+0

模板 類Nodo { 市民: Nodo(常量DNodo datoPasado, Nodo * izqPasado = NULL,NULL Nodo * derPasado = NULL) ();();();()()()()()()()()()() – HoNgOuRu

+0

樹中有多少個節點?這種訪問違規似乎是隨機發生的,還是在一定數量的節點之後發生? – Jason

1

由於pax認爲這可能是一個糟糕的指針。在Linux中,可能沒有嚴格的虛擬內存規則,因爲在其他地方運行代碼時(也取決於編譯器)。所以在Linux的情況下,它可能正在工作,但它可能實際上正在做你不期望的事情。

+0

Linux有嚴格的內存規則。然而,它可能是在Linux上,他有一個有效的隨機指針 – Dani

+0

是的,因爲malloc分配基於頁面的指針可以在頁面邊界有效。嚴格來說,我的意思是在Windows中某些由malloc調用的區域會標記爲PROTECTED,因此在釋放(有些情況下)之前或者在它們被調入之前不能實際使用它們 –