在函数中访问内存 malloc 时出现段错误
Segfault while accessing memory malloc'd in function
我正在尝试编写一个接受路径 (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 以将字符串放入其中,因此它不应该指向该函数的本地内存。非常感谢任何帮助。
您对 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;
}
并且不要忘记错误处理。为简洁起见,我已将其排除在本示例之外,但您不应将其排除在实际代码之外。
我正在尝试编写一个接受路径 (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 以将字符串放入其中,因此它不应该指向该函数的本地内存。非常感谢任何帮助。
您对 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;
}
并且不要忘记错误处理。为简洁起见,我已将其排除在本示例之外,但您不应将其排除在实际代码之外。