2009-11-05 44 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