C 例外的原因是什么?

C 例外的原因是什么?,c,windows,C,Windows,有人能找出错误的原因吗? 代码如下 #include <stdio.h> #include <conio.h> #include <string.h> int main(int argc, char *argv[]){ strcat(argv[1], ", Agniva welcomes you"); printf("%s", argv[1]); getch(); return 0; } 但如果我通过命令行获取一个不需要的额

有人能找出错误的原因吗? 代码如下

#include <stdio.h>
#include <conio.h>
#include <string.h>

int main(int argc, char *argv[]){
    strcat(argv[1], ", Agniva welcomes you");
    printf("%s", argv[1]);
    getch();
    return 0;
}
但如果我通过命令行获取一个不需要的额外参数,那么这个错误就会消失。你能说出是哪一个造成了这个问题吗?

strcat(argv[1],“,Agniva欢迎你”)

这正是原因所在-首先,您只能在以下情况下访问
argv[1]

if (argc > 1) // do something with argv[1]
第二,即使
argv[1]
指向有效的内存块-您只需用
strcat
覆盖它-将数据附加到它。在您的具体案例中,从堆中分配
argv[1]
,并将其大小写入内存块。因此,您得到的堆已损坏。

strcat(argv[1],“,Agniva欢迎您”)

这正是原因所在-首先,您只能在以下情况下访问
argv[1]

if (argc > 1) // do something with argv[1]

第二,即使
argv[1]
指向有效的内存块-您只需用
strcat
覆盖它-将数据附加到它。在您的具体案例中,从堆中分配
argv[1]
,并将其大小写入内存块。因此,您得到的堆已损坏。

这是我之前对该问题的评论,几乎是一个完整的答案


简言之,argv中没有为每个项分配额外的内存空间,因此当您尝试在其上strcat更多字符串时,您是在缓冲区外写入,这会导致未定义的行为。当您提供了一个额外的参数时,实际上您正在写入另一个参数所在的内存。同样,这是特定于实现的,当您在另一个平台(如Linux)上运行程序时,可能仍然会出现未定义的行为。

这是我之前对这个问题的评论,几乎是一个完整的答案


简言之,argv中没有为每个项分配额外的内存空间,因此当您尝试在其上strcat更多字符串时,您是在缓冲区外写入,这会导致未定义的行为。当您提供了一个额外的参数时,实际上您正在写入另一个参数所在的内存。同样,这是特定于实现的,当您在另一个平台(如Linux)上运行该程序时,可能仍然会出现未定义的行为。

您无法知道为argv[1]分配了多少内存,但仍试图用另外20多个字节对其进行存根

 strcat(argv[1], ", Agniva welcomes you");
也许是这样的

 if( argc < 2 )
        return -1;

    char *oBuf = calloc( strlen( argv[1] ) + 25 /* for this ", Agniva welcomes you" */ , 1);

    sprintf( oBuf, "%s%s",argv[1], ", Agniva welcomes you");
    printf("%s", oBuf);
    return 0;
if(argc<2)
返回-1;
char*oBuf=calloc(strlen(argv[1])+25/*为此,“Agniva欢迎您”*/,1);
sprintf(oBuf,“%s%s”,argv[1],“Agniva欢迎您”);
printf(“%s”,oBuf);
返回0;

您无法知道为argv[1]分配了多少内存,但仍试图用另外20多个字节对其进行存根

 strcat(argv[1], ", Agniva welcomes you");
也许是这样的

 if( argc < 2 )
        return -1;

    char *oBuf = calloc( strlen( argv[1] ) + 25 /* for this ", Agniva welcomes you" */ , 1);

    sprintf( oBuf, "%s%s",argv[1], ", Agniva welcomes you");
    printf("%s", oBuf);
    return 0;
if(argc<2)
返回-1;
char*oBuf=calloc(strlen(argv[1])+25/*为此,“Agniva欢迎您”*/,1);
sprintf(oBuf,“%s%s”,argv[1],“Agniva欢迎您”);
printf(“%s”,oBuf);
返回0;

欢迎来到!你好像迷路了。那很好。我已经投票将这个问题迁移到,在那里你可以得到专业的答案,这也是这个问题的正确位置。谢谢您的理解。@iBug大多数在这里发布编程问题的人这样做是因为他们在so上被禁止提问,这将导致迁移失败。因此,除非有特殊原因,我通常不会尝试迁移,例如,有人已经回答了这里,如果我们不迁移,答案将丢失。@DanHulme鉴于我编辑的内容质量和正确的格式,这一次可能值得一试。如果你愿意,我将不胜感激。谢谢,欢迎光临!你好像迷路了。那很好。我已经投票将这个问题迁移到,在那里你可以得到专业的答案,这也是这个问题的正确位置。谢谢您的理解。@iBug大多数在这里发布编程问题的人这样做是因为他们在so上被禁止提问,这将导致迁移失败。因此,除非有特殊原因,我通常不会尝试迁移,例如,有人已经回答了这里,如果我们不迁移,答案将丢失。@DanHulme鉴于我编辑的内容质量和正确的格式,这一次可能值得一试。如果你愿意,我将不胜感激。谢谢。虽然将argv视为只读是一种很好的做法,但实际上我们可以知道它指向有效的读/写内存,因为C标准5.1.2.2.1保证了这一点。因此,我们可以很好地向argv写入数据,这样做是定义良好且可移植的。但我们当然不能写得越界。因此,如果
argv[n]
“hello”
,那么我们只能可靠地向该数组写入最多5+1=6个字符。这不是一个好主意,但是得到了C标准的支持。@Lundin-是的,你是对的。内存,指向
argv[i]
当然是可写的。但很少有人能修改它。我只看到一种情况——在解析参数之前,如果程序使用不区分大小写的命令行语义,则大写或小写字符串。虽然将argv视为只读是一种良好的做法,但实际上我们可以知道它指向有效的读/写内存,因为C标准5.1.2.2.1保证了这一点。因此,我们可以很好地向argv写入数据,这样做是定义良好且可移植的。但我们当然不能写得越界。因此,如果
argv[n]
“hello”
,那么我们只能可靠地向该数组写入最多5+1=6个字符。这不是一个好主意,但是得到了C标准的支持。@Lundin-是的,你是对的。内存,指向
argv[i]
当然是可写的。但很少有人能修改它。如果程序使用不区分大小写的命令行语义,在解析参数之前,我只查看一个大小写字符串。这主要是对i的注释