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

时间:2018-11-02 18:14:15

标签: 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* 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;
}

问题是,当我通过'./a.out一二三四五'进行调用时,使用gdc引发了分段错误,我知道strcpy()会这样做。我只是学习它,无法真正找到原因。有人可以指出我做错了什么吗?

2 个答案:

答案 0 :(得分:1)

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

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 print_array(const char* arr[], int count) {
    for (int i = 0; i < count; i++) {
        printf("%s\n", arr[i]);
    }
}

答案 1 :(得分:1)

您的问题是char的数组数组与char的指针数组不同。看起来有些古怪,但是底层结构却不同。

实际上,您的编译器应发出警告(如果不是,则应提高警告级别)。

更具体地说,如果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;
}