题
我发现两种方式传递的命令行参数字阵列:
int main (int argc, char **argv)
{
const char *s1 = argv[0];
char s2[256];
strcpy(s2, argv[0]);
printf("s1: %s\ns2: %s\n\n", s1, s2);
}
编制与IBM xlc编译器在AIX系统的回报
[MyPrompt]>./a.出来
s1:./a.出来
s2:./a.出来
其执行情况(s1或s2)是否正确?s1是不错的,因为argv[0]可以是任何长度。s2中要求的长度argv[0] < 256符。
我不明白为什么s1应工作。我 想想 右手边的s1应要求在编制时间,但我 想想 它的产生,在运行时间。
解决方案
s1起作用的原因是因为argv [0] 的类型是指针。您只需分配地址(而不是实际值),这是安全的。您没有进行任何类型的分配或演员。
我通常更喜欢第一个选项,因为您应该只读取参数变量。
其他提示
如果您不想更改字符串,那么s1将起作用。
如果您想更改字符串,则可以复制它。如果你的系统支持它,你应该使用更安全的strnlen()和strncpy()。
我认为s1的右侧 应该在编译时需要, 但我认为它是由...产生的 运行时间。
不,每次遇到语句都需要它。例如:
void f() {
int x = 1;
...
}
每次调用函数时,整数x都将初始化为1,而不是在编译时。
s2具有令人愉快的财产是容易受到缓冲区溢出。
我已经看到改变人们的价值argv[0].在某些情况下,(在一些操作系统)改变argv[0]将会使程序出现在ps为什么你改变它。
如果您只是想引用参数而不对其进行任何更改,那么 s1 是正确的。
如果您需要以任何方式修改参数,那么您需要像 s2 示例中那样复制它,但在 s2 示例中,您需要明确检查查看长度是否比您要复制到的缓冲区长。例如,如果您正在使用像filename.jpg这样的参数作为输入并保存filename.gif作为输出,那么您需要复制该参数,因为您将把扩展名从.jpg更改为.gif
我会选择s1,特别是对于argv [n],其中n <!> gt;像s2这样的东西打开你的经典缓冲区溢出攻击。基本上,用户可以格式化长度超过256个字符的参数并覆盖堆栈上的信息,以便它们可以运行他们想要的任何代码。