【问题标题】:Segfault while accessing memory malloc'd in function访问内存 malloc 时出现段错误
【发布时间】:2016-09-27 16:03:18
【问题描述】:

我正在尝试编写一个函数,该函数接受路径 (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, "%s\n", 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: %d\n", count);
    fprintf(stderr, "1st: %s\n", out[0]); // segfaults here
    return 0;
}

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

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 以将字符串放入其中,因此它不应该指向该函数本地的内存。非常感谢任何帮助。

【问题讨论】:

  • char** split_path(char * path, int* count) {
  • 我会试一试,但我不知道为什么会有很大的不同。
  • @BLUEPIXY 所说的...或使用 char*** 所以 out 实际上会被更改并返回。
  • 效果很好,但为什么呢? out 是一个指针,为什么它不会被改变?我需要另一个级别的指针,比如 char** 吗?
  • 您没有访问函数中分配的内存。

标签: c string segmentation-fault malloc strcpy


【解决方案1】:

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, "%s\n", 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: %d\n", count);
    fprintf(stderr, "1st: %s\n", out[0]); // segfaults here

    free (out);
    return 0;
}

不要忘记错误处理。为简洁起见,我已将其从示例中省略,但您不应将其从实际代码中删除。

【讨论】:

  • 它有效!谢谢,我现在意识到,如果我想维护对 2d 内存数组的引用,我需要一个三重指针,就像我想要一个对单个 int 的引用一样,我需要一个 int 指针。有道理。
猜你喜欢
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 2020-07-04
  • 1970-01-01
  • 2017-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多