1

上記のプロセスが継続的に実行され、適切な順序で開始されることを確認するデーモンからプロセスを開始します。

ある時点で、プロセスを開始したいexecv()ので、引数用の文字列の配列を次のように準備します。

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])
);

これは、g++ 4.8.4 を使用した Ubuntu 14.04 で完全に機能していましたが、どういうわけか、c_str()g++ 5.3.1 でコンパイルされた同じコードを実行しようとすると、ポインターが無効になります。

execv()私の理解では、ベアポインタの配列を作成する最初のループと呼び出しの間で文字列を変更していないため、これはそうではありません。

リファレンスには次のように書かれています。

c_str() から取得したポインターは、次の方法で無効にすることができます。

  • 文字列への非 const 参照を標準ライブラリ関数に渡す、または
  • operator[]、at()、front()、back()、begin()、rbegin()、end()、rend() を除く、文字列に対する非 const メンバー関数の呼び出し。

PS私はすでに修正を行っていstdup()ますc_str()。可能であれば、文字列の余分なコピーを1つ避けたいと思っていました...

4

1 に答える 1