2016-05-31 17 views
-1

私は以下のようなC++プログラムを持っています。私はstd :: listをある関数から別の関数に値渡ししようとしています。私はリストがイテレータを使って呼び出し元関数でアクセス可能であると期待していますか?私は返信がstd::listのコピーコンストラクタを呼び出すことを期待し、それは呼び出し元でアクセス可能になります。私の仮定は間違っていますか?そうでない場合、なぜセグメンテーション違反が発生しますか?std :: listをある関数から別の関数に値渡しする

#include <list> 
#include <map> 
#include <string> 
#include <set> 
#include <iterator> 
#include <iostream> 

const char *sy_path = "/var/log"; 
struct Setting 
{ 
    typedef std::list<const Setting*> List; 

    const char*  path; 
    const char*  filename; 
    const char*  name; 

    int def; 
    int min; 
    int max; 

    struct Original 
    { 
     const char*  filename; 
     const char*  name; 

     Original(const char* filename_, const char* name_) 
        :filename(filename_), name(name_) 
     { 

     } 
    }original; 
    static const List settings(); 
}; 

const Setting::List Setting::settings() 
{ 
    const Setting c_settings[] = 
    {              //default min max  
     { sy_path, "cs.cfg",  "num_a",     1, 1, 29,   Original("sys.cfg", "num_a") } 
     ,{ sy_path, "cs.cfg",  "num_b",     1, 1, 6,    Original("sys.cfg", "num_b") } 
     ,{ sy_path, "cs.cfg",  "num_c",     1, 1, 29,   Original("sys.cfg", "num_c") } 
    }; 

    Setting::List lst; 

    int numelem = sizeof(c_settings)/sizeof(Setting); 
    for (int i = 0; i < numelem; i++) 
    { 
     const Setting & tmpSetting = c_settings[i]; 
     lst.push_back(&tmpSetting); 
    } 

    return lst; 
} 

static int get_settings(void) 
{ 
    Setting::List lst; 
    lst = Setting::settings(); 

    for (Setting::List::const_iterator it = lst.begin() ; it != lst.end(); ++it) 
    { 
     const Setting *cs = *it; 
     std::cout << "path: " <<cs->path << "filename: " <<cs->filename << "name: " << cs->name << std::endl; 
    } 
} 

int main() 
{ 
    get_settings(); 

    return 0; 
} 
+0

あなたは 'get_settings'でイテレートする前に、破壊されてから長い間のデータへのポインタのリストを返しています。リストを 'std :: list 'に変更してみてください。 – fbrereto

+1

なぜ、なぜ、なぜですか?問題ではありませんが、なぜ多くの人が初期化の代わりに課題を書いていますか? 'Setting :: List lst; lst = Setting :: settings();は 'Setting :: List lst = Setting :: settings();'でなければなりません。 Listオブジェクトを作成して直ちにそれを放棄する理由はありません。 –

答えて

1

はい、return lst;lstのコピーを返します。問題は、スタックにあるデータへのポインタ(const Setting c_settings[]変数)をlst個置くことです。これらのポインタは、関数から復帰すると無効になります。そのため、セグメンテーションフォルトが発生します。解決方法は、ヒープ上の設定にメモリを割り当てるか、またはstd::list<Setting>を使用することです。

typedef std::list<Setting> List; 

lst.push_back(c_settings[i]); // make sure you have the right copy constructor 

または

lst.push_back(new Setting(c_settings[i])); // make sure you have the right copy constructor 

また、私はconst char *の使用を避けるだろうし、代わりにstd::stringを使用しています。

+0

あなたは 'path'、' filename'、 'name'など' 'const char *'を審査していますか?そして、どのようにstd :: list を意味しますか? – liv2hak

+0

パス名、ファイル名、名前(この場合は、文字列リテラルで初期化しているので安全です)(sy_pathについてはわかりません)。しかし、 '' 'c_settings'''は、3つの設定要素をこの関数(およびスタック)にローカルに作成します。 '' 'std :: list ' ''私は、ポインタではなく、設定要素のリストを作ることを意味します。 – kaspersky

関連する問題