1

我的程序出现问题,其中出现了strsep()从 GDB 获得的分段错误,并且有错误消息

Program received signal SIGSEGV, Segmentation fault.
0x00002aaaaad64550 in strsep () from /lib64/libc.so.6

我的代码如下:

int split(char *string, char *commands, char *character) {
    char **sp = &string;
    char *temp;
    temp = strdup(string);
    sp = &temp;
    for (int i = 0; i < 100; i++) {
        commands[i] = strsep(sp, character);
        if (commands[i] == '\0') {
            return 0;
        }
        if (strcasecmp(commands[i], "") == 0) {
            i--;
        }
        printf("%d", i);
    }
    return 0;
}

任何帮助将不胜感激,因为我花了几个小时试图解决这个问题

该函数的参数是("Hello World", "@", "&")

编辑

所以我设法通过将代码更改为

int split(char* string, char* commands, char* character) {
        for(int i = 0; i < 100; i++) {
                commands[i] = strsep(&string, character);
                if(commands[i] == '\0') {
                        return 0;
                }
                if(strcasecmp(&commands[i], "") == 0) {
                        i--;
                }
        }
        return 0;
}

但是,现在我遇到了一个新问题,即返回每个索引都超出范围的空数组的命令。

编辑 2

我还应该澄清一下我想要做的事情,所以基本上命令是类型的char* commands[100],我想在修改原始指针数组并将“Hello World”存储到 commands[0] 时将它传递给函数我想在函数之外修改这个值。

4

1 回答 1

1

你的用法commands与函数原型不一致:调用者传递了一个 100 的数组char*commands应该是一个指向数组的指针char *,因此是一个类型char **commandsor char *commands[]。为了让调用者确定存储在数组中的令牌数量,您应该NULL在末尾存储一个指针或返回此数字或两者兼而有之。

存储commands[i] = strsep(...)不正确,因为commands定义为 a char *,而不是 a char **

令人惊讶的是,您会遇到分段错误,strsep()因为参数似乎正确,除非character碰巧是无效指针。

相反,您有未定义的行为很可能导致分段错误,strcasecmp(commands[i], "")因为commands[i]它是一个char值,而不是一个有效的指针。

这是修改后的版本:

// commands is assumed to point to an array of at least 100 pointers
// return the number of tokens or -1 is case of allocation failure
int split(const char *string, char *commands[], const char *separators) {
    char *dup = strdup(string + strcspn(string, separators));
    if (temp == NULL)
        return -1;
    char *temp = dup;
    char **sp = &temp;
    int i = 0;
    while (i < 99) {
        char *token = strsep(sp, separators);
        if (token == NULL) // no more tokens
            break;
        if (*token == '\0') // ignore empty tokens
            continue;
        commands[i++] = token;
    }
    commands[i] = NULL;
    if (i == 0) {
        free(dup);
    }
    return i;
}

分配给令牌的内存可以通过释放commands数组中的第一个指针来释放。复制这些令牌可能更简单,以便以更通用的方式释放它们。

于 2020-09-13T15:22:22.537 回答