2014-04-23 82 views
3

據我所知,堆應該是全球性的,不是嗎?所以我們應該可以在我們的函數中訪問我們想要的任何地方的堆內存。那麼爲什麼下面的代碼段錯誤(Segmentation Fault)?發生堆內存的範圍

#include <stdio.h> 
using namespace std; 

void A(int* x) 
{ 
    x = new int[10]; 
    for(int i = 0; i< 10; i++) 
    { 
    x[i] = i; 
    } 
} 

void B(int *x) 
{ 
    printf("%d", x[8]); 
} 

int main() 
{ 
    int* a = NULL; 
    A(a); 
    B(a); 
    return 0; 
} 
+0

如何A'的'的_input_參數應該影響'B'? – MSalters

回答

9

分割故障,因爲指針a正在由值來傳遞,以便內A()所做的更改是不可見的呼叫者,導致NULL指針內B()被解除引用。改正,通過引用傳遞指針A()

void A(int*& x) 
1

兩個A(a)和B(A)呼叫是按值一個。因此,A()或B()內部的任何更改都不會影響調用者。

請致電如,

void A(int*& a); 
2

至於其他的答案(S)表示,的確問題是,在A()分配的內存不傳遞到B()

但是,真的很好,請注意,您可以使用靜態分析和免費提供的工具來檢測此問題。

當我跑在你的榜樣clang++ version 3.4,它提供了:

$ make 
clang++ -Wall -Wextra --analyze -c -o go.o go.cpp 
go.cpp:16:16: warning: Array access (from variable 'x') results in a null pointer dereference 
    printf("%d", x[8]); 
       ^~~~ 
1 warning generated. 

如何真棒that‽在這個特殊的獨立的例子是額外的時間編譯器來評估的路徑是微不足道的。在「真實」代碼上可能會有更多開銷(而不是像這些合成示例)。但對於大多數用戶來說,這絕對是值得的。

2

問題:就我所知,堆應該是全球性的,不是嗎?

答案:是的。

聲明:所以我們應該能夠在我們的函數中的任何地方訪問堆內存。

回覆:是的,只要我們知道堆內存的價值,我們就可以。

問題:那麼爲什麼下面的代碼段錯誤(Segmentation Fault)?

答案:在一個函數中分配堆內存並不能保證內存值在其他函數中可見。由operator new返回的地址必須以某種方式提供給其他功能。您可以通過幾種方式做到這一點:

  1. 更改參數類型int*& a,由Subhajit的建議。

  2. A返回分配的內存地址。

    int* A() 
    { 
        int* x = new int[10]; 
        for(int i = 0; i< 10; i++) 
        { 
        x[i] = i; 
        } 
        return x; 
    }