C字符串中出现无法解释的额外字符问题求助
问题分析与修复方案
核心问题
strlen的工作逻辑:strlen会从字符串起始地址开始读取字节,直到遇到第一个'\0'(空终止符)才停止,返回的是终止符前的字符总数。你的代码中从未手动添加这个终止符,且malloc分配的内存是未初始化的垃圾值,因此strlen会一直读取超出你分配的内存范围,直到在某个随机位置碰到'\0',这就是返回值随机且偏大的根本原因。循环导致的缓冲区溢出:你的
while (i < size - 1)条件配合嵌套的for循环,会导致写入超出malloc分配的内存范围。例如当size=30时,第一次for循环会把i从0加到25,此时25 < 29(size-1=29),会再次执行for循环,i会继续增加到25+26=51,完全超出了malloc(30)分配的内存空间,这属于缓冲区溢出的未定义行为,进一步加剧了strlen结果的随机性。
修复步骤与代码
要让strlen返回预期的size值,需要做到两点:
- 分配内存时多留1字节存放
'\0' - 用安全的逻辑填充字符,并在最后添加终止符
修复后的代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *letters; int size, i = 0; scanf("%d", &size); if (size < (1024 * 1024)) { // 多分配1字节用于存放字符串终止符'\0' letters = malloc(size + 1); if (letters != NULL) { // 循环填充A-Z字符,避免缓冲区溢出 while (i < size) { letters[i] = 'A' + (i % 26); i++; } // 必须添加字符串终止符,否则strlen会读取垃圾值 letters[size] = '\0'; printf("%lu\n", strlen(letters)); free(letters); } } else { printf("Too much memory requested.\n"); } return 0; }
补充说明
- 如果坚持只分配
size字节内存,无法让strlen返回size——因为strlen必须依赖'\0'终止,此时最多只能让strlen返回size-1(将最后一个字节设为'\0')。 - 原代码的嵌套循环逻辑存在严重的越界风险,改用
i % 26的方式循环生成A-Z字符,既能简化代码,又能保证不会超出分配的内存范围。
内容的提问来源于stack exchange,提问作者Andres
相关产品推荐
相关产品推荐

