一开始,我写了类似的东西
char* argv[] = { "ls", "-al", ..., (char*)NULL };
execvp("ls", argv);
然而,GCC弹出了警告," C ++禁止将字符串常量转换为char*
。"
然后,我将代码更改为
const char* argv[] = { "ls", "-al", ..., (char*)NULL };
execvp("ls", argv);
结果,GCC弹出了错误,"从const char**
到char* const*
的转换无效。"
然后,我将代码更改为
const char* argv[] = { "ls", "-al", ..., (char*)NULL };
execvp("ls", (char* const*)argv);
它最终运行并且编译时没有任何警告和错误,但我认为这有点麻烦,我找不到有人在互联网上写过这样的东西。
有没有更好的方法在C ++中使用execvp
?
答案 0 :(得分:5)
你遇到了一个真正的问题,因为我们面临两个不兼容的约束:
C ++标准中的一个要求您必须使用const char*
:
在C中,字符串文字的类型为
char[]
,可以直接分配 到(非常)char*
。 C ++ 03也允许它(但不赞成使用它, 因为文字是C ++中的const)。 C ++ 11不再允许这样的分配 没有演员。
另一个来自遗留C函数原型,需要一个(非常量)char*
数组:
int execv(const char *path, char *const argv[]);
因此,某处必须有强制转换,我找到的唯一解决方案是包装execvp
函数。
这是该解决方案的完整运行C ++演示。不方便的是你有一些胶水代码可以写一次,但优点是你得到更安全,更清洁的C ++ 11 代码(最后nullptr
被检查)。
#include <cassert>
#include <unistd.h>
template <std::size_t N>
int execvp(const char* file, const char* const (&argv)[N])
{
assert((N > 0) && (argv[N - 1] == nullptr));
return execvp(file, const_cast<char* const*>(argv));
}
int main()
{
const char* const argv[] = {"-al", nullptr};
execvp("ls", argv);
}
您可以使用以下代码编译此演示:
g++ -std=c++11 demo.cpp
您可以在CPP Reference example for std::experimental::to_array
中看到类似的方法。
答案 1 :(得分:2)
这是execvp()
的声明(它不能修改其参数,为了向后兼容)和字符串文字的C ++解释为常量char
的数组之间的冲突。
如果演员关注你,你剩下的选择是复制参数列表,如下所示:
#include <unistd.h>
#include <cstring>
#include <memory>
int execvp(const char *file, const char *const argv[])
{
std::size_t argc = 0;
std::size_t len = 0;
/* measure the inputs */
for (auto *p = argv; *p; ++p) {
++argc;
len += std::strlen(*p) + 1;
}
/* allocate copies */
auto const arg_string = std::make_unique<char[]>(len);
auto const args = std::make_unique<char*[]>(argc+1);
/* copy the inputs */
len = 0; // re-use for position in arg_string
for (auto i = 0u; i < argc; ++i) {
len += std::strlen(args[i] = std::strcpy(&arg_string[len], argv[i]))
+ 1; /* advance to one AFTER the nul */
}
args[argc] = nullptr;
return execvp(file, args.get());
}
(您可能会认为std::unique_ptr
有点矫枉过正,但如果execvp()
失败,此函数会正确清理,并且函数会返回。)
演示:
int main()
{
const char *argv[] = { "printf", "%s\n", "one", "two", "three", nullptr };
return execvp("printf", argv);
}
one
two
three
答案 2 :(得分:0)
execvpe
需要char *const argv[]
作为第二个参数。也就是说,它需要一个指向非const数据的const指针列表。 C中的字符串文字是const,因此警告问题并将argv
强制转换为char* const*
是一种黑客攻击,因为execvp
现在可以写入argv
中的字符串。我看到的解决方案是为每个项目分配一个可写缓冲区,或者只使用execlp
代替const char*
args并允许传递字符串文字。