c语言 - 在功能中访问内存错误时出现隔离错误



我正在尝试编写一个函数,该函数接受路径(char *)并将其拆分为基于"/"分隔符的字符串数组。简化代码如下:

int split_path(char * path, char ** out) {
    out = NULL;
    char * token = strtok(path, "/");
    int count = 0;
    while(token) {
        out = realloc(out, sizeof(char*) * (++count));
        out[count-1] = malloc(sizeof(char) * strlen(token)+1);
        strcpy(out[count-1], token);
        fprintf(stderr, "%sn", out[count-1]);
        token = strtok(NULL, "/");
    }   
    out = realloc(out, sizeof(char*) * (count+1));
    out[count] = NULL;
    return count;
}
int main(int argc, char * argv[]) {
    char path[] = "/home/pirates/are/cool/yeah";
    char ** out;
    int count = split_path(path, out);
    fprintf(stdout, "count: %dn", count);
    fprintf(stderr, "1st: %sn", out[0]); // segfaults here
    return 0;
}

split_path函数中的所有 print 语句都完美打印,输出如下所示:

count: 1, string: home
count: 2, string: pirates
count: 3, string: are
count: 4, string: cool
count: 5, string: yeah
count: 5
1st: ./a.out
[1]    5676 segmentation fault (core dumped)  ./a.out

但是由于某种原因,当我回到主函数时,双字符数组不再有效。我认为这可能是因为它指向该split_path函数中声明的内存,但我正在执行 strcpy 以将字符串放入其中,因此它不应该指向该函数的本地内存。任何帮助将不胜感激。

您对out参数管理不善。main()中的out变量永远不会被分配有效的内存地址,因此存在段错误。 split_path() 中的 out 参数永远不会更新 main() 中的out变量。 您需要将变量的地址传递给split_path()以便它可以更新变量并访问变量指向的内存。

另请注意,strtok()修改它正在解析的字符串,因此您应该创建一个副本,然后解析副本,以免原始副本被销毁。 否则,请考虑使用 strchr() 而不是 strtok()

尝试更多类似的东西:

int split_path(char * path, char *** out) {
    *out = NULL;
    char * tmp = strdup(path);
    if (!tmp) { ... }
    char * token = strtok(tmp, "/"');
    int count = 0;
    char ** newout;
    while (token) {
        newout = realloc(*out, sizeof(char**) * (++count));
        if (!newout) { ... }
        *out = newout;
        (*out)[count-1] = malloc(sizeof(char) * (strlen(token)+1));
        if (!(*out)[count-1]) { ... }
        strcpy((*out)[count-1], token);
        fprintf(stderr, "%sn", token);
        token = strtok(NULL, "/");
    }   
    newout = realloc(*out, sizeof(char**) * (count+1));
    if (!newout) { ... }
    *out = newout;
    (*out)[count] = NULL;
    free (tmp);
    return count;
}
int main(int argc, char * argv[]) {
    char path[] = "/home/pirates/are/cool/yeah";
    char ** out;
    int count = split_path(path, &out);
    fprintf(stdout, "count: %dn", count);
    fprintf(stderr, "1st: %sn", out[0]); // segfaults here
    free (out);
    return 0;
}

并且不要忘记错误处理。为了简洁起见,我将其排除在此示例之外,但您不应将其排除在实际代码之外。

相关内容

  • 没有找到相关文章