繁体   English   中英

execv() 和常量

[英]execv() and const-ness

我经常在 C++ 中使用execv()函数,但是如果某些参数在 C++ 字符串中,我很恼火,我不能这样做:

const char *args[4];

args[0] = "/usr/bin/whatever";
args[1] = filename.c_str();
args[2] = someparameter.c_str();
args[3] = 0;

execv(args[0], args);

这不会编译,因为execv()需要char *const argv[]这与const char *不兼容,所以我必须使用strdup()将我的std::string s复制到字符数组,这很痛苦。

有谁知道这是什么原因?

Open Group Base Specifications 解释了这是为什么:为了与现有的 C 代码兼容。 但是,指针和字符串内容本身都不打算更改。 因此,在这种情况下,您可以使用const_cast -ing c_str()的结果。

引用:

包含关于argv[]envp[]是常量的声明是为了向未来的语言绑定作者明确这些对象是完全常量。 由于 ISO C 标准的限制,不可能在标准 C 中陈述这个想法。指定两个级别的const - exec 函数的argv[]envp[]参数的envp[]似乎是自然的选择,鉴于这些函数不修改指针数组或函数指向的字符,但这将不允许现有的正确代码。 相反,只有指针数组被标记为常量。

之后的表格和文字更加有见地。 但是,Stack Overflow 不允许插入表格,因此上面的引用应该足以让您在链接文档中搜索正确的位置。

const 是 C++ 的东西 - execv 在 C++ 存在之前就采用了 char * 参数。

您可以使用 const_cast 而不是复制,因为 execv 实际上并不修改其参数。 您可能会考虑编写一个包装器来节省自己的打字时间。

实际上,您的代码的一个更大问题是您声明了一个字符数组而不是一个字符串数组。

尝试: const char* args[4];

这只是 C/C++ 风格的 const 不能很好地工作的情况。 实际上,内核不会修改传递给 exec() 的参数。 它只会在创建新进程时复制它们。 但是类型系统的表现力不足以真正很好地处理这个问题。

这个页面上的很多人都建议让 exec 取“char**”或“const char * const[]”。 但是这些都不适用于您的原始示例。 “char**”意味着一切都是可变的(对于字符串常量“/usr/bin/whatever”当然不是这样)。 “const char *const[]”意味着没有什么是可变的。 但是你不能为数组的元素分配任何值,因为数组本身就是常量。

你能做的最好的事情就是有一个像这样的编译时 C 常量:

const char * const args[] = {
  "/usr/bin/whatever",
  filename.c_str(),
  someparameter.c_str(),
  0};

这实际上适用于建议的“const char *const[]”类型签名。 但是如果你需要可变数量的参数怎么办? 那么你不能有一个编译时常量,但你需要一个可变数组。 所以你又回到了捏造的事情上。 这就是 exec 的类型签名采用“const char **”作为参数的真正原因。

顺便说一下,这些问题在 C++ 中是一样的。 您不能将 std::vector < std::string > 传递给需要 std::vector < const std::string > 的函数。 您必须对整个 std::vector 进行类型转换或复制。

我通常用以下方法破解它:

#define execve xexecve
#include <...>
#include <...>
#include <...>
#undef execve

// in case of c++
extern "C" {
    int execve(const char * filename, char ** argvs, char * const * envp);
}

;/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM