2016-11-20 17 views
0
#include <iostream> 

class C 
{ 
    private: 
     int *o; 
    public: 
     C(int &i) { *o = i;} 
     int* get_val() {return o;} 
}; 

int main() 
{ 
    int t = 9; 
    C c(t); 
    int* p = c.get_val(); 
    std::cout<<*p<<std::endl; 
    int* h = c.get_val();   //seg fault 
    std::cout<<*h<<std::endl; 

    int f = 25; 
    C g(f); 
    int* q = g.get_val();   //seg fault 
    std::cout<<*q<<std::endl;   

    return 0; 
} 

クラスCには「c」と「g」の2つのオブジェクトがあります。 プライベート変数のポインタを返すのは初めてでは問題ありませんが、2回目に呼び出されたときにsegフォルトが発生します。それはなぜそうですか?C++では、異なるオブジェクトのプライベート変数のポインタを返すと、セグメンテーションフォルトが発生するのはなぜですか?

私は2番目の呼び出しをコメントアウトし、新しいオブジェクトの作成を試み、プライベート変数のポインタを返そうとしました。 「g」はクラスCの別のオブジェクトですが、それを返すとセグメンテーション違反になります。それはなぜそうですか?

+3

'C(int&i){* o = i;}'これは、初期化されていないポインタを逆参照することによって、未定義の動作を示します。あなたは 'o =&i;'を意味するかもしれません。 [デモ](http://rextester.com/CINTK58780) –

+0

ありがとう、それは動作します! – Harikrishnan

答えて

2

コンストラクタC :: C(int)は、メンバ変数oを初期化しません。 * o = iを介してポインタoを書き込もうとしますが、oは初期化されていないため、結果は予測できません。あなたが割り当て前にポインタに

C(int &i) { *o = i;} 

1

あなたはすでにスペースが割り当てられていません。それはしてきたはずです。

C(int i):o(new int){o=i;} 

しかし、クラスの関数の内部メモリを割り当てるには、あなたが体系的にそれらにdelete/delete[]を適用する必要があることが必要です。まあ、これはメモリリークを防ぐためです。要するに、次のものが必要です。

C::~C(){ 
    delete o; // Freeing the memory associated with each object 
} 

また、私はあなたの実装では、参照によって値を渡すためのユースケースを考えることはできません。そこでC(int &i)C(int i)に変更しました。

1

C :: oを初期化していません。問題は、プライベートポインタを返すことではありません。割り当てられていないメモリに割り当てていることです。

ここでライン8(Cのコンストラクタ)にブレークポイントと、GDBからの出力です:私のマシン上で

Breakpoint 1 at 0x400960: file tmp.cc, line 8. 

Breakpoint 1, C::C (this=0x7fffffffdd00, [email protected]: 9) at tmp.cc:8 
8   C(int &i) { *o = i;} 
$1 = (int *) 0x7fffffffddf0 
9 
9 

Breakpoint 1, C::C (this=0x7fffffffdce0, [email protected]: 25) at tmp.cc:8 
8   C(int &i) { *o = i;} 
$2 = (int *) 0x0 

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000400969 in C::C (this=0x7fffffffdce0, [email protected]: 25) at tmp.cc:8 
8   C(int &i) { *o = i;} 

は、最初の呼び出しは成功しましたが、g.oは0x0ですので、2回目の呼び出しは、セグメンテーションフォルトが発生します。

* oに割り当てる前にC :: oを初期化する必要があります。

C(int &i) : o(new int) { *o = i;} 
関連する問題