C语言中从函数返回二维字符串数组的问题求助
问题根源
你代码的核心问题是:parse函数里的new_sentence是栈上的局部数组,当函数执行完毕返回时,栈帧会被销毁,这块内存会被操作系统回收或后续函数调用覆盖。此时返回它的地址,main里拿到的是一个无效的野指针,访问它属于未定义行为。
解决方案
下面提供三种可行的修复方案,你可以根据场景选择:
方案1:使用静态数组
把局部数组改为静态存储类型,这样数组会存放在程序的静态存储区,函数结束后不会被销毁。
#include <string.h> #include <stdio.h> // 修改返回值类型为指向char数组的指针 char (*parse(char *s))[15]; int main () { char str[1000] = "This-is-test-sentence"; char (*n_sentence)[15] = parse(str); for (int j = 0; j<4; j++) { printf("%s\n", n_sentence[j]); } return 0; } char (*parse(char *s))[15] { char *delim = "-"; char *token; // 改为静态数组 static char new_sentence[4][15]; token = strtok(s, delim); int numberOfWord = 0; while( token != NULL && numberOfWord <4 ) { // 增加边界检查,避免越界 strcpy(new_sentence[numberOfWord], token); token = strtok(NULL, delim); numberOfWord++; } return new_sentence; }
注意:静态数组是全局唯一的,多次调用parse会覆盖之前的结果,不适合多线程或需要保留历史数据的场景。
方案2:动态分配内存
在堆上分配二维数组,内存由程序员手动管理,用完后需要释放,避免内存泄漏。
#include <string.h> #include <stdio.h> #include <stdlib.h> // 返回指向char数组的指针,同时传出单词数量 char **parse(char *s, int *word_count); int main () { char str[1000] = "This-is-test-sentence"; int word_count = 0; char **n_sentence = parse(str, &word_count); for (int j = 0; j<word_count; j++) { printf("%s\n", n_sentence[j]); // 先释放每个子字符串的内存 free(n_sentence[j]); } // 再释放外层指针数组的内存 free(n_sentence); return 0; } char **parse(char *s, int *word_count) { char *delim = "-"; char *token; // 先统计单词数量 char *temp_str = strdup(s); // 复制原字符串避免被strtok修改 token = strtok(temp_str, delim); int count = 0; while(token != NULL){ count++; token = strtok(NULL, delim); } free(temp_str); // 分配外层指针数组 char **new_sentence = malloc(count * sizeof(char*)); if(new_sentence == NULL) return NULL; // 重新分割原字符串 token = strtok(s, delim); int idx = 0; while( token != NULL ) { // 分配每个单词的内存并复制 new_sentence[idx] = strdup(token); token = strtok(NULL, delim); idx++; } *word_count = count; return new_sentence; }
这种方案更灵活,支持任意数量的单词,且不会覆盖之前的数据,但需要注意正确释放内存。
方案3:调用者提供缓冲区
由main函数提前分配好数组,传给parse函数填充,无需处理内存分配,更安全。
#include <string.h> #include <stdio.h> // 传入缓冲区和缓冲区最大容量,返回实际填充的单词数 int parse(char *s, char (*buf)[15], int max_words); int main () { char str[1000] = "This-is-test-sentence"; char n_sentence[4][15]; // main里定义缓冲区 int word_count = parse(str, n_sentence, 4); for (int j = 0; j<word_count; j++) { printf("%s\n", n_sentence[j]); } return 0; } int parse(char *s, char (*buf)[15], int max_words) { char *delim = "-"; char *token; token = strtok(s, delim); int numberOfWord = 0; while( token != NULL && numberOfWord < max_words ) { strcpy(buf[numberOfWord], token); token = strtok(NULL, delim); numberOfWord++; } return numberOfWord; }
这种方案最安全,没有内存泄漏风险,适合已知单词数量上限的场景。
内容的提问来源于stack exchange,提问作者Muhammet Rıdvan İNCE
相关产品推荐
相关产品推荐

