strcpy()在可变大小的字符串数组上生成分段错误

strcpy()在可变大小的字符串数组上生成分段错误,c,C,我正在学习“C”语言,我创建了一个程序,如下所示,它将命令行参数复制到另一个可变大小的数组(字符串),并从索引2开始打印该数组 #include <stdio.h> #include <string.h> void print_array(const char* arr[]) { for (int i = 0; arr[i]; i++) { printf("%s\n", arr[i]); } } void copy_array(char

我正在学习“C”语言,我创建了一个程序,如下所示,它将命令行参数复制到另一个可变大小的数组(字符串),并从索引2开始打印该数组

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

void print_array(const char* arr[]) {
    for (int i = 0; arr[i]; i++) {
        printf("%s\n", arr[i]);
    }
}

void copy_array(char* dest[], const char* src[]) {
    for (int i = 0; src[i]; i++) {
        strcpy(dest[i], src[i]);
    }
}

int main(int argc, const char* argv[]) {
    if (argc < 2)
        return 1;
    char args[argc][256];
    copy_array(args, argv);
    print_array(&args[2]);
    return 0;
}
#包括
#包括
无效打印数组(常量字符*arr[]{
for(int i=0;arr[i];i++){
printf(“%s\n”,arr[i]);
}
}
无效复制_数组(char*dest[],const char*src[]{
for(int i=0;src[i];i++){
strcpy(dest[i],src[i]);
}
}
int main(int argc,const char*argv[]{
如果(argc<2)
返回1;
字符args[argc][256];
复制_数组(args,argv);
打印数组(&args[2]);
返回0;
}

问题是,当我通过“./a.out一二三四五”调用它时,它抛出了一个分段错误。使用gdc,我可以看到strcpy()实现了这一点。我只是在学习,找不到真正的原因。有人能指出我做错了什么吗?

似乎复制数组循环在数组的实际长度之后执行

void copy_array(char* dest[], const char* src[]) {
    for (int i = 0; src[i]; i++) {
        strcpy(dest[i], src[i]);
    }
}
应改为

void copy_array(char* dest[], const char* src[], int count) {
    for (int i = 0; i < count; i++) {
        strcpy(dest[i], src[i]);
    }
}
void copy_数组(char*dest[],const char*src[],int count){
for(int i=0;i
此外,打印阵列应更改为:

void print_array(const char* arr[], int count) {
    for (int i = 0; i < count; i++) {
        printf("%s\n", arr[i]);
    }
}
void print_数组(常量字符*arr[],整数计数){
for(int i=0;i
您的问题是
字符的数组与指向
字符的指针数组不同。这似乎有些迂腐,但其基本结构却不同

事实上,编译器应该发出警告(如果不是,则应该提高警告级别)

更具体地说,如果
a
是一个字符数组,那么
a[i]
是一个相对于数组开头的地址,只能计算该地址,因为编译器知道每个子数组有多大(例如,在您的情况下,
256

然而,如果
a
是指向
char
的指针数组,则不需要计算,
a[i]
包含指针本身的值

通过在需要指针数组的位置传递数组,会导致编译器错误地计算地址(即未定义的行为),从而导致错误

如果您希望保持一致并在任何地方使用指针数组,您的代码可能更像:

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

void print_array(char* arr[]) {
    for (int i = 0; arr[i]; i++) {
        printf("%s\n", arr[i]);
    }
}

void copy_array(char* dest[], char* src[]) {
    int i;
    for (i = 0; src[i]; i++) {
      dest[i] = malloc(strlen(src[i]) + 1);
      strcpy(dest[i], src[i]);
    }
    dest[i] = NULL;
}

int main(int argc, char* argv[]) {
    if (argc < 2)
        return 1;
    char *args[argc + 1];
    copy_array(args, argv);
    print_array(&args[2]);
    return 0;
}
#包括
#包括
#包括
无效打印数组(字符*arr[]{
for(int i=0;arr[i];i++){
printf(“%s\n”,arr[i]);
}
}
无效复制_数组(char*dest[],char*src[]{
int i;
对于(i=0;src[i];i++){
dest[i]=malloc(strlen(src[i])+1;
strcpy(dest[i],src[i]);
}
dest[i]=NULL;
}
int main(int argc,char*argv[]){
如果(argc<2)
返回1;
字符*args[argc+1];
复制_数组(args,argv);
打印数组(&args[2]);
返回0;
}

使用固定长度的缓冲区会导致难看的缓冲区溢出错误。为什么不
strdup
?看起来像是家庭作业。Jaymin Suthar,您使用的编译器没有警告行
copy_数组(args,argv)?我在Ubuntu机器上使用gcc 8.2.0,很抱歉之前没有提及,编译器确实警告过我。您的参数错误,copy_数组应该采用char*或char dest[],char*[]与char**相同,对于strcpy不正确,“argv”是字符串数组,您需要传递其中一个,而不是全部。
argv[argc]
将始终是NULL@FatalError,我无法理解你在我的回答中试图指的是什么谢谢你的解释,它奏效了。现在我也更了解数组和指针。