2009-11-05 69 views
4

我想編寫一個老派的參數向量(argv的)的函數中使用轉換的std ::矢量<char*>到C風格的參數向量繼承

INT的execve(爲const char *文件名, char * const argv [],char * const envp []);

我與STL ::矢量類試過:

std::string arguments = std::string("arg1");  
std::vector<char*> argv; 
char argument[128]; 
strcpy(argument, arguments.c_str()); 
argv.push_back(argument); 
argv.push_back('\0'); // finish argv with zero 

最後我通過向量的execve()

execve的( 「bashscriptXY」 &的argv [0] ,NULL)

代碼編譯但是argV被execve()忽略了。所以這似乎是錯誤的,我正在嘗試。我應該如何用C++高效地構建argV?

+2

何必複製字符串到一個數組?如果你有一個'std :: string',並且你想要一個'char *'C風格的NUL終止字符串,那麼'c_str()'就已經返回了。 – 2009-11-05 20:37:20

回答

4

我認爲的char [128]是多餘的,因爲該字符串地方都會有相同的壽命,也嘗試加入該計劃將以argv [0]像rossoft他回答說:

const std::string arguments("arg1");  
std::vector<const char*> argv; 

argv.push_back("bashscriptXY"); 
// The string will live as long as a locally allocated char* 
argv.push_back(arguments.c_str()); 
argv.push_back(NULL); // finish argv with zero 

execve(argv[0], &argv[0], NULL); 
+2

對於「用零結束argv」,我更喜歡「argv.push_back(0)」或「argv.push_back(NULL)」。 「argv.push_back('\ 0')」會導致正確的結果,但是會讓你對這裏發生的事情思考太多 - 並且存在將它誤寫爲「argv.push_back(」\ 0「 )「這將是錯誤的...... – hjhill 2009-11-05 21:57:45

+1

同意,我很喜歡說你的意思。 – joshperry 2009-11-05 23:17:56

+0

「...因爲字符串本地將具有相同的生命...」它確實,但採取其'c_str()'後的字符串更改可能是災難性的。所以你可能想把它作爲一個const字符串。 – sbi 2009-11-05 23:41:06

5

請注意argv[0]始終是命令本身的名稱。所以,如果你想1個參數傳遞給一個程序,你需要填寫兩個元素:

argv[0]應該是「bashscriptXY」(或任何你想要的......)
argv[1] = "your_argument"

1

除非參數是硬編碼,你將不得不做一些動態內存分配。首先,爲參數個數創建一個字符指針數組,然後爲每個參數分配內存並複製數據。

This question非常相似,並且包含一些代碼解決方案。

+0

「execve()不會成功返回,並且調用進程的文本,數據,bss和堆棧會被加載的程序覆蓋。調用的程序會繼承調用進程的PID,以及任何打開的文件描述符不會在exec上關閉。「 - 我認爲動態分配會泄漏,我不認爲execve釋放()s argv char * s – joshperry 2009-11-05 20:30:51

+0

@joshperry:儘管如此,我認爲沒關係。您希望程序的argv數組「被泄漏」,因爲C運行時(在這種情況下是OS)在程序(進程)退出時爲您執行。一個沒有在退出時清理泄漏資源的OS可能不會執行任何exec函數來實際執行任何操作。 – 2009-11-06 00:08:22

2

數問題:

  • argv數組的第一個元件被認爲是程序名稱
  • argv載體可以採取 char const*類型作爲 execve()不會修改參數(雖然被調用的進程可能會 - 但是這些將會在它自己的地址空間中進行復制)。所以你可以推動 c_str()字符串。 (見註釋)

嘗試了這一點:

// unfortunately, execve() wants an array of `char*`, not 
// am array of `char const*`. 
// So we we need to make sure the string data is 
// actually null terminated 
inline 
std::string& null_terminate(std::string& s) 
{ 
    s.append(1, 0); 
    return s; 
} 

// ... 

std::string program = std::string("bashscriptXY"); 
std::string arg1("arg1"); 
std::string arg2("arg2"); 

null_terminate(program); 
null_terminate(arg1); 
null_terminate(arg2); 

std::vector<char *> argv; 

argv.push_back(&program[0]); 
argv.push_back(&arg1[0]); 
argv.push_back(&arg2[0]); 
argv.push_back(NULL); // finish argv with zero 

intptr_t result = execve(program.c_str(), &argv[0], NULL); 
+0

這不能在不添加const_cast的情況下進行編譯。 「無效的從」const char **「轉換爲」char * const *「 – 2010-10-03 17:07:55

+0

@Parker:你會在這裏放置一個const_cast? – 2012-04-19 07:46:15

+1

@Nathan:原來Parker是對的 - POSIX標準給出了一種'char * const []'到'argv'參數(即使爲新進程創建了一個字符串的副本),所以編譯器會在你試圖傳遞一個'char const *'數組的時候報錯。我的代碼片段放在一個不太符合標準的頭文件中(可能是MSVC的'process.h'),你可以在'&argv [0]'參數上加一個'const_cast ',但我不確定我很興奮 – 2012-04-19 08:34:51