我正在写一个C程序。它从commandLine获取它的参数。我想改变代码中的commandLine参数。由于它们被定义为“const char *”,所以我无法使用“strcpy”,“memcpy”,......来更改它们。另外,我知道,我不能将它们的类型从“const char *”更改为“char * ”。 有什么方法可以改变它们吗?改变命令行参数
非常感谢你提前。
此致敬礼, 沙迪。
我正在写一个C程序。它从commandLine获取它的参数。我想改变代码中的commandLine参数。由于它们被定义为“const char *”,所以我无法使用“strcpy”,“memcpy”,......来更改它们。另外,我知道,我不能将它们的类型从“const char *”更改为“char * ”。 有什么方法可以改变它们吗?改变命令行参数
非常感谢你提前。
此致敬礼, 沙迪。
根据C99§5.1.2.2.1/ 1,为main
签名
int main(int argc, char *argv[]) { /* ... */ }
所以你是允许删除const
。只要不会导致比原始参数更长的字符串溢出,或尝试安装比最初传递的参数更多的参数。
其他人基本上是对的,你应该而不是创建一个副本。
C没有的那些真棒向量之一? ;-) – 2010-04-16 17:43:25
@James:rofl,一次为我处理太多问题提供了正确的方法。 – Potatoswatter 2010-04-16 17:47:00
这个标准甚至不仅仅是从参数类型中推断出的内容,还特别指出:“参数argc和argv以及argv数组指向的字符串应该可以通过程序修改...” – 2010-04-16 18:05:59
不,你不能修改这些。但是,没有规则将它们复制到新的缓冲区并使用它们。
这可能并不重要,但不能用strcpy()和memcpy()都不能改变任何东西。后缀'cpy'是复制的简称(不出意外)。
关于更改argv指针,您当然可以更改指针,但为什么?如果你想让命令行参数不是所给出的东西,只需忽略它们,并使用你喜欢的任何值。还要注意,argv是一个参数,因此对main()是本地的;如果在其他地方需要它,则必须将其作为参数传递,或将其另存为全局变量。
re。 “你不能用'strcpy()''改变任何东西;如果它没有改变任何东西,那将是毫无意义的。如果你做'strcpy(argv [0],“foo”);',它会改变('argv [0]'的内容)。 – Arkku 2010-04-16 20:42:22
如果将const char *更改为主函数的char *,则无关紧要。
只有一件你必须关心的是缓冲区溢出strcpy。
根据ELF规范(参见图3-31堆栈布局),http://refspecs.linuxbase.org/elf/abi386-4.pdf,功能参数区后面跟着环境值区。
argv是指向每个参数的指针数组,environ也是指向每个环境var = value字符串的指针数组。 所以布局如下。
argv[0] --> 1st parameter
argv[1] --> 2nd parameter
argv[2] --> 3rd parameter
...
NULL
--------------------------------------- memory boundary between param and env
environ[0] --> 1st env_var=env_value
environ[1] --> 2nd env_var=env_value
environ[2] --> 3rd env_var=env_value
...
NULL
所以,如果你复制非常长的字符串到argv [0],它可以溢出param和env之间的边界。 在这种情况下,您必须将argv和环境内存区域移动到下面的另一个堆空间。 我从Postgresql开源代码中提取了以下示例代码。 ps_status.c)
char ** new_environ;
char ** new_argv;
char ** org_argv;
int i;
new_argv = (char **) malloc((argc + 1) * sizeof(char *));
for (i = 0; i < argc; i++)
new_argv[i] = strdup(argv[i]);
new_argv[argc] = NULL;
org_argv = argv;
argv = new_argv;
new_environ = (char **) malloc((i + 1) * sizeof(char *));
for (i = 0; environ[i] != NULL; i++)
new_environ[i] = strdup(environ[i]);
new_environ[i] = NULL;
environ = new_environ;
然后,你可以使用getopt的,GETENV等 他们将读取新分配的内存区域的值。另外,如果更改原始参数(org_argv [0]),则可以在ps命令中操作进程的输出名称。 (也在顶部,htop实用程序) 请参阅下文。
$> ps -ef | grep my_proc
dplee 10855 1 0 7월28 pts/2 00:00:16 my_proc i can manipulate this name
为什么你需要改变命令行参数?如果您正在修改它们以传递到程序的另一部分,则可能需要复制并修改它。 – WildCrustacean 2010-04-16 17:27:06
你有没有想过将参数复制到不同的变量并使用它? – Jacob 2010-04-16 17:27:32