首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这里使用strdup()?

为什么这里使用strdup()?
EN

Stack Overflow用户
提问于 2021-10-09 09:04:34
回答 2查看 96关注 0票数 4

我正在读“操作系统:三个简单的部分”。在第五章中,有一段代码展示了exec()系统调用的用法。

代码语言:javascript
复制
    1 #include "common.h"
    2
    3 int main(int argc, char ** argv) {
    4     printf("hello world (pid: %d)\n", (int) getpid());
    5     int rc = fork();
    6     if (rc < 0) {
    7         fprintf(stderr, "fork failed\n");
    8         exit(1);
    9     } else if (rc == 0) {
   10         printf("hello, I am child (pid: %d)\n", (int) getpid());
   11         char *myargs[3];
   12         myargs[0] = strdup("wc");
   13         myargs[1] = strdup("p3.c");
   14         myargs[2] = NULL;
   15         execvp(myargs[0], myargs); // run work count
   16         printf("this shouldn't print out\n");
   17     } else {
   18         int wc = wait(NULL);
   19         printf("hello, I am parent of %d (wc: %d) (pid: %d)\n", rc, wc, (int) getpid());
   20     }
   21     return 0;
   22 }
   23

为什么在第12~14行使用strdup()?我试着用下面的代码替换这个部分:

代码语言:javascript
复制
   12         myargs[0] = "wc";                                                                                                                                                                                     
   13         myargs[1] = "p3.c";
   14         myargs[2] = NULL;

它的工作原理和前一个一样。

EN

回答 2

Stack Overflow用户

发布于 2021-10-09 13:09:59

代码会根据您的更改进行编译,但可能会触发未定义的行为。

execvp需要参数char *const argv[]。而不是char上丢失的const。因此,execvp可以自由地写入传递给它的字符串。

String literals in C不可修改:

字符串文字是不可修改的(实际上可以放在只读内存中,比如.rodata)。如果程序试图修改由字符串文字形成的静态数组,则行为是未定义的。

所以代码的作者希望是安全的,并对字符串文字进行strdup,以获得字符串的可修改版本。

请注意,C++是更严格的,在那里,gcc会发出

警告: ISO C++禁止将字符串常量转换为'char*‘-Wwrite- string

用于您的代码。

如果execvp不修改arg字符串,那么最好有一个表示这一点的签名(const char *const argv[])。

票数 1
EN

Stack Overflow用户

发布于 2021-10-09 17:33:16

您的代码版本很好。与Werner的回答相反,它不会导致未定义的行为。

根据the POSIX spec的说法,execvp的功能原型是

代码语言:javascript
复制
int execvp(const char *file, char *const argv[]);

单独考虑,这意味着可以修改argv数组中字符串的内容,尽管该数组的指针元素本身不能修改。如果是这样,那么确实有必要传递一个指向可写字符串的指针数组,比如strdup提供的,而不是字符串文字,因为写入字符串文字确实是未定义的行为。这可能就是代码的作者所想的。

然而,规范的文本为我们提供了更多信息:

指针的argv[]和envp[]数组以及这些数组所指向的字符串不得通过调用其中一个exec函数来修改,除非是替换进程映像的结果。

因此,事实上,可以保证execvp不会修改这些字符串。因此,传递字符串字面量是完全安全的。原始代码的作者可能不知道这个保证。

下面的理由解释了为什么他们选择了原型(“关于argv[]和envp[]是常量的声明包含在...”)。正如沃纳建议的那样,const char *const argv[]似乎更好地表达了实际行为。然而,C的指针转换规则意味着,如果它们有,那么代码就像

代码语言:javascript
复制
char *args[5];
args[0] = /* some writable string */;
...
execvp(file, args);

不会编译,即使在原则上它是完全没问题的。其基本原理包括对const在C中的语义以及它们如何使其无法正确编写的礼貌含糊的大肆抨击。

Can I pass a const char* array to execv?上还有一些进一步的讨论。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69505245

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档