2016-05-08 3 views
1

私はそう私は、文字列の配列を作成し、私はexecv()でプロセスを開始するいくつかの時点でg ++ 4.8.4とg ++ 5.3.1の間でc_str()のライフタイムが変更されましたか?

など、プロセスが継続的に実行し、適切な順序で始めると述べたことを確認するデーモンからプロセスを起動しますそのような引数:

std::vector<std::string> args; 
args.push_back("--debug"); 
args.push_back("--connect"); 
args.push_back("10.0.0.5:4040"); 
... 

ほとんどの場合、私は約10の引数を持っています。

今、execv()は、裸のポインタの配列にのみアクセスします。だから私は、このようなポインタの配列を作成するために、次の手順を実行します

std::vector<char *> args_p; // sorry, my code actually uses std::vector<char const *> args_p -- so constness is fine here 
for(auto a : args) 
{ 
    args_p.push_back(a.c_str()); 
} 
args_p.push_back(nullptr); // list needs to be null terminated 

その後、私はその最後の配列でexecv()を呼び出すことができます。

execv(
    args_p[0], 
    const_cast<char * const *>(&args_p[0]) 
); 

グラムでのUbuntu 14.04で完全に働いていた++ 4.8.4、何らかの形で、g ++ 5.3.1でコンパイルされた同じコードを実行しようとすると、c_str()ポインタが無効になります。

裸のポインタの配列を作成する最初のループとexecv()呼び出しの間の文字列を変更しないので、私が理解している通りです。

referenceは言う:

  • 任意の標準ライブラリ関数に文字列への非const参照を渡す、または
  • c_strから得られたポインタが()によって無効にされてもよいです

  • operator []、at()、front()、back()、begin()、rbegin()、end()およびrend()を除く、文字列上の非constメンバー関数の呼び出し。

P.S.私はすでに修正をしていますが、今はのうちstdup()を実行しています。 char const*を返し、args_pvector<char*>あるc_str()

for(auto a : args) 
{ 
    args_p.push_back(a.c_str()); 
} 

まず、:私だけは、可能ならば...ここ

+2

それは働いたことはありません。それはちょうどに現われた。あなたは未定義の振る舞いをしている – juanchopanza

+2

'auto&a:args' –

+0

@ T.C。ああ、それは 'auto const&a:args'でなければなりません。 –

答えて

2

2つの問題を文字列のいずれかの余分なコピーを避けるために期待していました。 constcharにポインタが必要なので、&a[0]を使用する必要があります。

第2に、aは、ループの各繰り返しの最後に範囲外になります。したがって、あなたが保持しているポインタは、あなたの下から破壊されます。あなたはargsに実際の文字列へのポインタを必要とする - あなたは参照することにより反復する必要があります:

for(auto& a : args) 
{ 
    args_p.push_back(&a[0]); 
} 
+1

申し訳ありませんが、間違いなくここでは、裸のポインタの配列は 'char const *'です。主な問題は、 'auto a:args'が文字列のコピーを作成し、そのコピーが各繰り返しで「消える」ということです。それが実際に働いたことは奇妙です。私は 'auto const&a:args'を使ってみましたが、' strdup() 'がなければ正常に動作します。ちょうど前のように! –

+0

'&a [0]'だけを使用すると、文字列はnullで終了します( ''\ 0' ')。 –

+0

空文字列に対して&a [0] 'が失敗します。コードが空の文字列を含んでいないことをコードが保証していても、それは認識すべきことです。 –

関連する問題