2017-07-07 103 views
-3

爲什麼下面的代碼只有當我沒有cout語句時纔會發生段錯誤(使用g ++ -std = C++ 11 test.cpp運行): 爲什麼下面的代碼給分段錯誤,只有當我沒有COUT語句(以克++ -std = C++ 11 TEST.CPP運行)只有在不使用cout的情況下C++段錯誤

#include <iostream>                     
#include <string> 
#include <ctype.h> 
#include <stdio.h> 
#include <algorithm> 
#include <vector> 
using namespace std; 


struct node { 
     int data; 
     node *left; 
     node *right; 

     node(int d, node *l, node *r) : data{d}, left{l}, right{r} {} 
}; 

node* findNode(node *root, node *find) { 

    if (!root) return nullptr; 

    if (root->data == find->data) { 
      return root; 
    } 

    node *left, *right; 

    if (root->left) left = findNode(root->left, find); 
    if (root->right) right = findNode(root->right, find); 

    // Uncomment this to avoid a segfault. Why ? 
    //cout << "left = " << left << " right = " << right << " find = " << find << endl; 

    if (left && left->data == find->data) { 
      return left; 
    } 
    if (right && right->data == find->data) { 
      return right; 
    } 
    return nullptr; 
} 


int main() { 

    node *newNode1 = new node(20, nullptr, nullptr); 
    node *newNode2 = new node(60, nullptr, nullptr); 

    node *root = new node(50, newNode1, newNode2); 

    findNode(root, newNode1); 

    return 0; 
} 
+0

無法重現。代碼爲我編譯和符合 – Fureeish

+7

您可能未初始化'left'和'right',導致未定義的行爲。所以奇怪的東西是相同的課程。 – Sneftel

+1

你有UB,正在泄漏內存。調查智能指針(和stl容器)並初始化變量。 –

回答

2

node *left, *right;產生未初始化指針,它們的值是未定義的。看起來你最初依靠的是nullptr,但事實並非如此。

當您達到if(left && left->data == find->data)的條件時,除非之前指定left,否則您正在檢查未初始化變量(left)的值。從一個未初始化的變量讀取未定義的行爲,這意味着它可以做任何事情,包括崩潰,看起來工作正常或完全不可預知的事情。由此產生的行爲可能隨時因任何原因而發生變化,包括與問題無關的變化。嘗試推理爲什麼具有未定義行爲的程序除了簡單地指出它是未定義的行爲之外,還做了它的工作。

一個解決方案是,讓自己永遠處於未初始化狀態的指針初始化爲NULL:

node *left = nullptr; 
node *right = nullptr; 
+0

「這是未定義的行爲,這意味着它可以做任何事情」 - 嚴格來說它是*更糟*;當你的程序的一部分調用UB時,編譯器被允許執行*任何它想要的* - 包括將你的代碼的其他部分編譯爲你沒有想到的東西 - UB不*本地化到你寫的地方, *您的所有*代碼。 –

+1

@JesperJuhl我認爲「什麼」幾乎涵蓋了所有的東西。 –

+0

沒錯。我只是覺得需要明確。 UB經常被誤解爲隻影響展示UB的代碼,實際上它可能會影響到所有的程序。 –

相關問題