gpt4 book ai didi

c - 在调用exec *()系列函数时,argv的char *元素是否必须唯一?

转载 作者:太空狗 更新时间:2023-10-29 14:56:56 24 4
gpt4 key购买 nike

我正在尝试编写一个小型实用程序,将其参数列表中继到一个exec'd进程,除了在构建新进程的参数列表时会重复一些传入的参数。

以下是我要执行的操作的非常简化的版本,该版本仅重复了每个参数一次:

#include <stdlib.h>
#include <unistd.h>

#define PROG "ls"

int main(int argc, char* argv[] ) {

int progArgCount = (argc-1)*2;
char** execArgv = malloc(sizeof(char*)*(progArgCount+2)); // +2 for PROG and final 0
execArgv[0] = PROG;
for (int i = 0; i<progArgCount; ++i)
execArgv[i+1] = argv[i/2+1];
execArgv[progArgCount+1] = 0;

execvp(PROG, execArgv );

} // end main()

注意 execArgv的元素不是唯一的。具体来说,每个重复项中的两个元素是相同的,这意味着它们指向内存中的相同地址。

标准C对此用法有什么说法吗?是不正确的行为还是未定义的行为?如果不是,那还是不明智的,因为执行程序可能取决于 argv元素的唯一性?如果我错了,请纠正我,但是由于程序不是const,程序是否可能无法直接修改其 argv元素?这样做会冒着风险,使执行程序错误地修改 argv[1](例如)然后访问 argv[2],错误地假设这两个元素指向独立的字符串吗?我可以肯定,几年前我开始学习C/C++时就自己做了,而且我认为当时 argv元素可能不是唯一的。

我知道执行涉及“过程镜像的替换”,但是我不确定这到底意味着什么。我可以想象,这可能涉及将给定的 argv参数(在上面的示例中为 execArgv)深复制到新的内存分配中,这可能会使事情变得唯一,但我对exec函数的内部知识并不了解。而且,这至少是浪费的,至少是如果可以在“替换”操作中保留原始数据结构,那么这就是我怀疑它发生的原因。也许不同的平台/实现在这方面表现不同?回答者可以对此发表意见吗?

我试图找到有关此问题的文档,但只能从 http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html中找到以下内容:

The arguments specified by a program with one of the exec functions shall be passed on to the new process image in the corresponding main() arguments.



上面的内容并没有阐明是否是传递给新过程的参数的唯一深度复制。

The argument argv is an array of character pointers to null-terminated strings. The application shall ensure that the last member of this array is a null pointer. These strings shall constitute the argument list available to the new process image. The value in argv[0] should point to a filename that is associated with the process being started by one of the exec functions.



同上。

The argv[] and envp[] arrays of pointers and the strings to which those arrays point shall not be modified by a call to one of the exec functions, except as a consequence of replacing the process image.



老实说,我不知道如何解释以上内容。 “替换过程镜像”是exec函数的重点!如果要修改数组或字符串,则从某种意义上讲,这将构成“替换过程镜像的结果”。这几乎意味着exec函数将修改 argv。此摘录只是加剧了我的困惑。

The statement about argv[] and envp[] being constants is included to make explicit to future writers of language bindings that these objects are completely constant. Due to a limitation of the ISO C standard, it is not possible to state that idea in standard C. Specifying two levels of const-qualification for the argv[] and envp[] parameters for the exec functions may seem to be the natural choice, given that these functions do not modify either the array of pointers or the characters to which the function points, but this would disallow existing correct code. Instead, only the array of pointers is noted as constant. The table of assignment compatibility for dst= src derived from the ISO C standard summarizes the compatibility:



还不清楚“关于argv []和envp []是常量的语句”指的是什么。我的主要理论是指文档页面顶部给出的原型(prototype)中参数的const限定。但是,由于这些限定词仅标记指针,而不标记 char数据,因此很难明确指出“这些对象是完全恒定的”。其次,我不知道为什么该段提到“语言绑定(bind)的作者”。绑定(bind)到什么?这与exec函数上的常规文档页面有何关系?第三,该段的主要目的似乎是说,为了向后兼容已建立的ISO C标准,我们不得不将 char元素所指向的字符串的实际 argv内容保留为非常量。现有的正确代码”。文档页面上的下表对此进行了确认,在此不再赘述。尽管在摘录的中间确实很清楚地表明exec函数本身不会以任何方式修改给定的 argv对象,但是这些都不能果断地回答我的主要问题。

我将不胜感激有关我的主要问题的信息,以及对我的解释和对引用的文档摘录的理解的注释(特别是如果我的解释有任何错误的话)。谢谢!

最佳答案

Does Standard C say anything about this usage? Is it incorrect, or undefined behavior?



如果两个指针指向相同的存储位置,则没有问题。这不是未定义的行为。

If not, is it still inadvisable, since the exec'd program might depend on the uniqueness of its argv elements?



POSIX标准未指定有关argv元素唯一性的任何内容。

Please correct me if I'm wrong, but isn't it possible for programs to modify their argv elements directly, since they're non-const?



C Standards#5.1.2.2.1p2
The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.
因此,答案是-是的,这是可能的。

Wouldn't that create a risk of the exec'd program blithely modifying argv[1] (say) and then accessing argv[2], falsely assuming that the two elements point to independent strings?



在计算中, exec是操作系统的功能,该操作系统在现有进程的上下文中运行可执行文件,以替换先前的可执行文件。

因此,当执行 exec家族系统调用时,参数中给出的程序将被加载到调用者的地址空间中,并在那里覆盖该程序。结果,一旦指定的程序文件开始执行,调用者地址空间中的原始程序就消失了,并由新程序和存储在新替换的地址空间中的参数列表 argv替换。

POSIX标准说:
The number of bytes available for the new process' combined argument and environment lists is {ARG_MAX}. It is implementation-defined whether null terminators, pointers, and/or any alignment bytes are included in this total.
ARG_MAX:
{ARG_MAX}
Maximum length of argument to the exec functions including environment data.

这意味着为新的流程参数分配了一些空间,并且可以安全地假定参数字符串已复制到该空间。

I know that exec'ing involves "replacement of the process image", but I'm not sure what that entails exactly.



检查 this

And perhaps different platforms/implementations behave differently in this respect? Can answerers please speak to this?



实现因平台而异,但是Unix的所有变体都必须遵循相同的POSIX标准,以保持兼容性。因此,我相信所有平台上的行为都必须相同。

关于c - 在调用exec *()系列函数时,argv的char *元素是否必须唯一?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47815506/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com