当num_samples2=252时,这段C语言代码为何触发无限循环?
为什么这段C代码会触发无限循环?
咱们先看你贴的代码片段:
if (num_samples2 == 252) { char buffer[1024]; char* p = buffer; for(int a = 1; a < num_samples2 - 6; a = a + 6){ p += sprintf(p, "%f,",data_samples[a]); p += sprintf(p, "%f,",data_samples[a+1]); p += sprintf(p, "%f,",data_samples[a+2]); p += sprintf(p, "%f,",data_samples[a+3]); p += sprintf(p, "%f,",data_samples[a+4]); p += sprintf(p, "%f",data_samples[a+5]); } }
核心原因是栈缓冲区溢出引发的未定义行为,意外篡改了循环相关变量,最终导致无限循环,具体拆解如下:
- 理论循环次数与实际缓冲区不匹配:当
num_samples2=252时,循环条件是a < 252-6=246,a从1开始每次加6,正常来说循环会执行40次左右(最后一次a=241,下一次a=247就不满足条件退出)。但你定义的buffer只有1024字节,每次循环要写入6个double类型的格式化字符串——随便一个123.456789,这样的字符串就占10个字符,一次循环至少写60多字节,40次下来总需求超过2400字节,远远超出buffer的容量上限。 - 栈溢出篡改循环变量:
buffer是栈上的局部数组,栈内存布局里,循环变量a、甚至num_samples2如果是局部变量的话,通常位于buffer的高地址侧。当sprintf不管不顾地往buffer外写数据时,就会覆盖这些变量:- 如果把
a的值改成远小于246的数(比如被溢出的数据冲成1),循环条件会永远满足,自然无限运行; - 如果把
num_samples2改得特别大,num_samples2-6也会随之变大,a永远追不上这个值,循环也停不下来。
- 如果把
这种情况属于C语言里的未定义行为,溢出后的表现不一定每次都完全一致,但无限循环是很常见的结果。
给你几个解决思路:
- 换成更安全的
snprintf,它能限制写入的字节数,从根源避免溢出; - 提前计算好所需的缓冲区大小,确保能装下所有输出内容;
- 或者用
malloc动态分配足够大的缓冲区。
内容的提问来源于stack exchange,提问作者John Dign
相关产品推荐
相关产品推荐

