我很好奇C完全解析命令行参数。例如,假设我有一个名为myProgram
的程序,它接受两个这样的参数
./myProgram arg1 arg2
如果我打电话
./myProgram arg1$'\0otherstuff' arg2
如果我们打印arg1
和arg2
,忽略argv[1]
, argv[2]
和$'\0otherstuff'
仍会打印,但它会在哪里播出?它存储在arg1
后面的内存中吗?它可能会覆盖任何缓冲区吗?如果前面有arg2
个字符,null
怎么读?
答案 0 :(得分:1)
将./myProgram arg1 arg2
转换为C样式int argc, char *argv[]
由操作系统或shell(取决于)完成。 C不解析参数,你解析C中的参数.C是一种编程语言,而不是实体。形式int argc, char *argc[]
在C编程语言中用作传递给main函数的参数,但其他编程语言可能使用不同的形式,对于C,请参见main_function。
在linux中,可以使用execve系统调用来指定传递给函数的参数。从./myProgram arg1 arg2
形式解析到execve参数是由shell(例如bash)完成的,它构造argv数组并将参数传递给execve调用。
你的shell可能忽略了$'\0otherstuff'
部分,因为在POSIX下,flename不能包含NUL字符(假设你的shell与POSIX兼容)。
答案 1 :(得分:0)
调用可执行文件时,您的操作系统内核将采用其他参数(作为纯文本)并将它们传递到程序存储器中。 在调用main函数之前,会执行一个小代码,它将给定的参数传递给C中的实际main函数。
答案 2 :(得分:0)
尝试使用bash(版本3.2.57(1)-release(x86_64-apple-darwin17))表明示例中的“otherstuff”未传递给程序。当使用您显示的命令行调用程序时,sudo apt-get install --reinstall
指向的内存包含“arg1”,然后是空字符,然后是“arg2”。因此,命令行中的null和“otherstuff”尚未传递给程序。
(假设:如果shell将它传递给程序,我希望它会在argv[1]
所指向的内存中传递它,并且它不会有覆盖任何缓冲区的危险如果shell被设计为容忍参数中嵌入的空字符,我希望(基于我们如何设计事物)它将参数视为一个完整的字符串并提供必要的空间来保存它。)
“arg2”之前的参数包含空字符的事实与“arg2”的处理无关。在初始处理命令行之后,shell不会将该行视为一个字符串。它将其分为单词或其他单元,并使用自己的数据结构处理它们。因此,先前参数中存在空字符对后面的参数没有影响。
此外,shell可能无法传递包含嵌入空字符的参数。通常用于执行程序的例程(例如argv[1]
)将参数接受为以null结尾的字符串。因此,嵌入的null终止字符串,execl
例程永远不会传递超出空字符的任何内容。