C语言内存分配与输入处理问题求助
解决动态字符串数组的段错误问题
你遇到的两个段错误,核心原因都是指针传递方式错误,再加上一点细节逻辑问题:
问题根源拆解
指针按值传递,主函数拿不到修改后的数组
leArgs函数里的char **arg是按值传进来的,你在函数里用realloc修改arg的指向,只会改这个局部变量,主函数里的str还是一开始的NULL。所以不管你在leArgs里存了多少内容,主函数访问str[0]都是在操作空指针,直接触发段错误。索引逻辑的小瑕疵
虽然第一次循环时args和数组长度的对应没问题,但num_args先自增再分配内存,用num_args-1作为索引比依赖args变量更稳妥,能避免循环次数多了可能出现的索引越界。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #define INVERSO "inverso" #define LEN_INVERSO 8 #define TRUE 1 #define FALSE 0 #define FIM_LINHA -1 #define NOTVALID -1 #define BUFFER 65535 enum arg {PRIMEIRO, SEGUNDO, TERCEIRO, QUARTO, QUINTO}; int is_space ( int c ) { return (c == '\t' || c == ' ' || c == '\n'); } int NotEndOfLine ( char character ) { return character != '\n'; } int leNome ( char *buff ) { int character, aspas = FALSE, i = 0; // 跳过前导空白,处理直接输入换行的情况 while ( is_space (character = getchar()) ) { if ( !NotEndOfLine(character) ) { buff[0] = '\0'; return FIM_LINHA; } } do { if (character == '\"') aspas = (aspas == FALSE) ? TRUE : FALSE; else buff[i++] = character; } while ( !is_space(character = getchar() ) || aspas == TRUE ); buff[i] = '\0'; // 修正:i已经指向字符串末尾,无需再i++ return !NotEndOfLine ( character ); } // 改成指向指针的指针,让函数能修改主函数里的str指针 int leArgs ( char ***arg ) { int num_args = 0, args = PRIMEIRO, lenght, endline; char buff[BUFFER]; do { endline = leNome( buff ); printf("Run: %d\n" , args); if ( endline == FIM_LINHA ) return num_args; // 操作主函数传来的指针地址,更新数组 *arg = realloc(*arg, sizeof(char*) * (++num_args)); if (*arg == NULL) { perror("realloc失败"); exit(EXIT_FAILURE); } lenght = strlen(buff); // 用num_args-1做索引,避免args变量的干扰 (*arg)[num_args - 1] = malloc(sizeof(char) * (lenght + 1)); if ((*arg)[num_args -1] == NULL) { perror("malloc失败"); exit(EXIT_FAILURE); } strcpy((*arg)[num_args - 1], buff); printf("buff:%s num_args:%d\n", buff, num_args); printf("Argumento: %s\n", (*arg)[num_args - 1]); putchar('\n'); args++; } while ( endline == FALSE ); return num_args; } int main(){ int i, num_args; char **str = NULL; // 传递str的地址给leArgs num_args = leArgs(&str); if (num_args > 0) { printf("%s ", str[0]); puts("sucesso "); for(i = 0; i < num_args; i++){ printf("i:%d ", i); printf("%d:%s\n", i, str[i]); } // 释放动态分配的内存,避免泄漏 for(i = 0; i < num_args; i++){ free(str[i]); } free(str); } else { puts("没有输入任何有效参数"); } return 0; }
关键修复点说明
- 指针传递方式修改:把
leArgs的参数改成char ***arg,主函数传递&str,这样函数内部对*arg的修改会直接同步到主函数的str指针,解决了主函数拿不到数组的问题。 - 字符串终止符修正:
leNome里原代码的buff[i++] = '\0'会导致字符串末尾多占一个无用字节,改成buff[i] = '\0'更准确。 - 添加内存分配失败检查:
realloc和malloc可能返回空指针,加个判断能提前发现错误,避免后续崩溃。 - 空输入判断:主函数里先检查
num_args是否大于0,避免用户没输入内容时访问空指针。 - 内存释放:动态分配的内存一定要记得释放,防止内存泄漏。
- 索引逻辑简化:用
num_args-1作为数组索引,不再依赖args变量,代码逻辑更清晰,减少出错可能。
内容的提问来源于stack exchange,提问作者stfp04
相关产品推荐
相关产品推荐

