2016-10-01 5 views
-1

https://stackoverflow.com/a/236803/6361644に記載されている次のコードを使用して、文字列をベクトルに解析して各要素を空白で区切って次のコードを書きました。このコードの後ベクトルに分割された文字列<char*>はベクトル要素を上書きします

std::string line = "ls -l -a"; 
std::string cmd; 
std::vector<char*> argv; 
std::stringstream ss; 
ss.str(line); 
std::string tmp; 
getline(ss, cmd, ' '); 
argv.push_back(const_cast<char*>(cmd.c_str())); 
while(getline(ss, tmp, ' ')) 
    argv.push_back(const_cast<char*>(tmp.c_str())); 
argv.push_back(NULL); 

印刷argvが、私は2番目の要素は上書きされている理由はわからない

{gdb) print argv                   
$22 = std::vector of length 3, capacity 4 = {0x26014 "ls", 0x2602c "-a", 0x2602c "-a", 0x0} 

を与えます。任意のヒントをいただければ幸いです。

+0

リンク先の回答に記載されているコードを実際に使用していませんでした。 – Barry

答えて

2

あなたは邪魔にならないような方法でポインタを格納しています.Cスタイルの文字列へのポインタを格納する適切な方法はではなくconst char*です。この中

(-corrected const)ループ:

std::vector<const char*> argv; 
// ... 
while(getline(ss, tmp, ' ')) 
    argv.push_back(tmp.c_str()); 

すべての後続の反復は、あなたが保存されていた以前のポインタを無効に、tmpをクリアします。 tmp.c_str()を押し戻すとすぐにgetline()が解放されます。したがって、その後のすべてのアクセスは未定義です。

あなたがあなたの代わりにフルstringを格納することによって行うことができ、すべての文字列の所有権を取得する必要があります。

std::vector<std::string> argv; 
// ... 
while(getline(ss, tmp, ' ')) 
    argv.push_back(std::move(tmp)); 

そして今argvは、実際に独自のリソースのすべてを所有しています。

-1

c_str()によって返されたポインタは、std::stringの内部データを指しています。

このポインタは、文字列が破棄されるか、または変更されるまで有効です。 std::stringが破壊または変更されると、ポインタは無効になります。

while(getline(ss, tmp, ' ')) 
    argv.push_back(const_cast<char*>(tmp.c_str())); 

すでに赤い旗で離れconst -nessをキャストの問題、さておき:毎回tmpの内容がssファイルの次の行に置き換えますwhileループ反復します。

これは、whileループの以前の繰り返しで取得されたc_str()を自動的に無効にします。

正しい解決策は、すべての個々の単語を最初にstd::vector<std::string>に解析することです。

次に、このベクトルが初期化されたら、ベクトルを反復処理し、個々の文字列のc_str()を取得して生の文字ポインタのベクトルを構築します。

std::stringの代わりにstd::vector<char>を使用し、各ベクターの最後に明示的な '\ 0'文字を追加すると、醜いconst_castは必要ありません。

+0

ヌル終端文字列を格納するのに 'ベクトル'をお勧めしますか?それはまさに 'string'のためのものです。 -1。 – Barry

+0

彼は明らかな 'exec()'のために 'char *'が必要なので、 –

+1

間違ったコンテナを使用し、ヌルターミネータで手作業でmuckingするのは、 'const_cast'よりも醜いです。 –

関連する問題