Argc / Argv C问题

时间:2010-05-07 21:11:18

标签: c

如果我有以下代码:

main(int argc, char *argv[]){
 char serveradd[20];
 strcpy(serveradd, argv[1]);
 int port = atoi(argv[2]);
 printf("%s %d \n", serveradd, port);

打印命令行的前两个参数。但是,如果我这样做:

 char serveradd[20];
 strcpy(serveradd, argv[1]);
 int port = atoi(argv[2]);
 char versionnum[1]; 
 strcpy(versionnum, argv[3]);
 printf("%s %d %s \n", serveradd, port, versionnum);`

第一个参数(serveradd)不会打印到屏幕上而没有存储...为什么会发生这种情况?如何解决?谢谢!

6 个答案:

答案 0 :(得分:10)

char versionnum[1];  
strcpy(versionnum, argv[3]); 

疯狂的猜测,但你用这些线粉碎堆栈。让versionnum更大;就目前而言,它只能安全​​地保持空字符串。

答案 1 :(得分:3)

你可能正在用

来记忆
char versionnum[1]; 
strcpy(versionnum, argv[3]);

假设任何非空的以空字符结尾的字符串将是> 1个字符长。

永远不要使用直接strcpy();改为使用strncpy()(注意 - 1以保留空终止符的空间):

char serveradd[20] = { 0 };
strncpy(serveradd, argv[1], sizeof(serveradd) - 1);
int port = atoi(argv[2]);
char versionnum[2] = { 0 }; 
strcpy(versionnum, argv[3], sizeof(versionnum) - 1);
printf("%s %d %s \n", serveradd, port, versionnum);

答案 2 :(得分:1)

使用strcpy而不使用正在复制的字符串的strlen来测试长度,以确保它适合目标缓冲区是一个非常糟糕的主意。您应该使用strncpy,这是经过长度检查的,不会超出目标缓冲区。

您不能将字符串存储在长度为1的char数组中,因为null终止符占用一个字符,因此您可以存储的所有字符都是空字符。几乎可以肯定你是在超越你的缓冲区。

答案 3 :(得分:1)

我认为上面的答案解决了你的问题,但是在将来尝试在调试时对内存分配更加慷慨。如果您认为需要5个元素,请创建一个定义make it 10,然后如果您想为null终止符留出空间,则将其更改为5或6。此外,如果您发现自己分配了一个长度为1的数组,请停下来问问原因。如果你有一个元素,只需使用一个普通变量。

每当我遇到argc和argv的问题时,首先想到的就是将它们打印出来,看看我是否有我想的那样。

答案 4 :(得分:0)

它以你描述的方式对我有用。我的猜测是你在其中一个字符串中超过了字符限制。我使用strncpy而不是strcpy。

答案 5 :(得分:0)

尝试strdup()

另一种方法是使用strdup()在堆上分配内存,这样就不会溢出缓冲区。在你的情况下,因为变量将在程序的生命周期中存在,所以这不是很糟糕,或者你可以使用free()在上次使用变量之后立即释放内存。确保之后不要使用变量!下面是一些示例代码。


#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

int main(int argc, char *argv[])
{
      char *serveradd  = NULL;
      int   port;
      char *versionnum = NULL;

      if (argc != 4)
      {
            printf("Usage: %s SERVERADD PORT VERSIONNUM\n", argv[0]);
            exit(126);
      }

      serveradd  = strdup(argv[1]);
      port       = atoi(argv[2]);
      versionnum = strdup(argv[3]);

      if ((serveradd == NULL) || (versionnum == NULL))
      {
            perror("Could not allocate command line arguments");
            exit(125);
      }

      printf("%s %d %s \n", serveradd, port, versionnum);

      free(serveradd);
      free(versionnum);
      serveradd  = NULL;
      versionnum = NULL;
      exit(0);
}