C语言中strcmp函数导致段错误

3

当我使用strcmp时,似乎出现了段错误:奇怪的是,该值似乎是正确存储的,但仍会导致段错误。有人知道为什么会发生这种情况吗?以下是我的代码:

比如说,我想要取消别名的值为'xx',在for循环之后的两行代码它们都等于'xx',但接着这一行会导致段错误:if (alias_array[i].alias != NULL && strcmp(alias_array[i].alias, arguments[1]) == 0) {

typedef struct alias {
    char alias[50];
    char command[50];
} alias;

alias alias_array[MAX_ALIAS_LEN];

void unalias_command(char *arguments[50]) {
    char alias_name[50];
    strcpy(alias_name, arguments[1]);
    printf("args[1] %s\n", *arguments);
    printf("Len of args = %ld", strlen(arguments[1]));
    //if(strcmp(alias_name, NULL) != 0) {      
    if (arguments != NULL) {
        int found = 0;
        for (int i = 1; i < MAX_ALIAS_LEN; i++) {
            printf("current name = %s\n", alias_array[1].alias);
            printf("current argument = %s\n", arguments[1]);
            if (alias_array[i].alias != NULL && strcmp(alias_array[i].alias, arguments[1]) == 0) {
                // if alias is found and matches then we can use the free() function
                found = 1;
                strcpy(alias_array[i].alias, NULL);
                strcpy(alias_array[i].command, NULL);
                break;
            }
        }
        if (found == 1) {
            printf("Alias, %s has been removed as an alias\n", arguments);
        } else {
            printf("No alias with name %s\n", arguments[1] );
        }
    } else {
        printf("Error: command 'unalias' requires 1 argument"); }
}

... 

char *args[50] = {""}
unalias_command(args)

你的“for循环后的第2行”(或其中的第一行)显示了alias_array [1] .alias的值,但是strcmp使用的是alias_array [i] .aliasi1不同)。由于您没有向我们展示alias_array是如何声明或初始化的,因此我们只能猜测该数组包含无效的字符串数据。 - Adrian Mole
什么是alias_array?如果它是一个alias数组,那么alias_array[i].alias != NULL就没有意义了。请发布一个最小可复现示例,即展示错误的最短完整代码。 - Weather Vane
@AdrianMole,我现在已经在typedef声明下的代码中使用alias_array进行了编辑。 - tDownUnder
@jDownUnder 好的,但是我发布的答案仍然有效,chqrlie 给出的答案也是如此。 - Adrian Mole
@AdrianMole,更奇怪的是,如果我这样做if( alias_array[i].alias[0] != '\0' && strcmp(alias_array[i].alias, arguments) == 0) {,它似乎并不会出现段错误。 - tDownUnder
显示剩余3条评论
2个回答

2
如果您传递了一个包含单个空字符串和50个空指针的字符串数组:
    char *args[50] = {""}
    unalias_command(args)

您在此处收到了分段错误:

   strcpy(alias_name, arguments[1]);

同时,这里还有:

   printf("Len of args = %ld", strlen(arguments[1]));

进一步的问题:
  • alias 结构体的成员不是指针,因此比较 alias_array[i].alias != NULL 没有意义。
  • strcpy(alias_array[i].alias, NULL); 行为未定义。你应该改写为 strcpy(alias_array[i].alias, ""); 或者简单地写成 *alias_array[i] = '\0';

你应该像 main() 函数接收到的那样传递参数计数和参数数组,并且必须在处理命令之前检查是否使用正确:

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

typedef struct alias {
    char alias[50];
    char command[50];
} alias;

alias alias_array[MAX_ALIAS_LEN];

int unalias_command(int argc, char *arguments[50]) {
    char *alias_name;
    if (argc < 2) {
        fprintf(stderr, "unalias: missing argument\n");
        return 1;
    }
    // no need to copy the alias, just use a char pointer
    alias_name = arguments[1];
    if (alias_name[0] != '\0') {
        int found = 0;
        for (int i = 0; i < MAX_ALIAS_LEN; i++) {
            if (strcmp(alias_array[i].alias, alias_name) == 0) {
                // if alias is found and matches then we can reset it
                found = 1;
                *alias_array[i].alias = '\0';
                *alias_array[i].command = '\0';
                break;
            }
        }
        if (found) {
            printf("Alias `%s' has been removed as an alias\n", alias_name);
            return 0;
        } else {
            printf("No alias with name `%s'\n", alias_name);
            return 1;
        }
    }
}

@chqlie 我的问题不在于参数为空,因为我正在制作一个shell,它有600多行,所以我不能包含所有行,这不是问题,那只是我的参数初始化。 - tDownUnder
@jDownUnder:好的,但是正如我在我的详细回答中所解释的那样,还有其他问题。 - chqrlie

1
请注意,检查if (alias_array[i].alias != NULL)实际上没有做任何有意义的事情。 .alias成员被声明为一个固定的char[50]数组,因此在该表达式中,它将衰减为指针(指向该数组的第一个元素)。 在任何有意义的数据集中,这不能是NULL
您需要其他方法来测试alias_array [i] .alias成员是否表示有效字符串。 可能是if (alias_array[i] .alias [0]!= '\0')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接