You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

strtok()偶发栈溢出?程序异常现象及原因咨询

strtok()异常行为及栈溢出问题解答

问题背景

使用Kubuntu 22.04 LTS系统、Kate v22.04.3编辑器及gcc v11.3.0编译器,编写了测试strtok()字符串分割功能的C程序,代码如下:

#include <stdio.h>
#include <string.h>

int main(void)
{
   char inString[] = "";         // string read in from keyboard.
   char * token    = "";         // A word (token) from the input string.
   char delimiters[] = " ,";     // Items that separate words (tokens).
   
   // explain nature of program.
   printf("This program reads in a string from the keyboard"
          "\nand breaks it into separate words (tokens) which"
          "\nare then output one token per line.\n");
   printf("\nEnter a string: ");
   scanf("%s", inString);
   
   /* get the first token */
   token = strtok(inString, delimiters);
   
   /* Walk through other tokens. */
   while (token != NULL)
   {
      printf("%s", token);
      printf("\n");
      
      // Get next token.
      token = strtok(NULL, delimiters);
   }
   return 0;
}

运行时出现异常:

  • 首次输入fred , steve , nick,仅输出"f"和"ed"
  • 第二次输入steve , barney , nick,输出"s"和"eve"后触发栈溢出检测并终止程序
  • 测试发现首个token为4字符时程序可勉强运行,5字符及以上则触发栈溢出

a) 为何首个token总是在第二个字符处被拆分?

核心问题是char inString[] = "";仅分配了1字节内存(仅能存空终止符'\0')。用scanf("%s", inString)输入字符串时,输入的字符会直接越界写入相邻的栈内存——刚好覆盖了token指针的存储位置。

比如输入"fred"时,inString的内存被越界写入:inString[0] = 'f',inString[1] = 'r',而token变量就在相邻地址,于是token的内容被篡改,指向了inString+2(也就是字符'e'的地址)。后续strtok的操作和输出,都是基于被破坏后的指针,看起来就像token在第二个字符处被拆分。

b) 为何后续token无法输出?

首先,scanf("%s", inString)只会读取到第一个空白字符就停止,输入的"fred , steve..."实际上只有"fred"被读入(还越界了),后面的", steve..."根本没被读取。

其次,inString的内存溢出已经破坏了栈上的其他数据,包括strtok内部依赖的静态状态变量,导致strtok无法正确识别后续token,直接出现异常行为。

c) 为何首个token长度大于4字符会引发栈溢出?

栈上的变量是连续分配的:inString(1字节)、token(64位系统下占8字节)、delimiters(3字节)依次排列在栈中。输入字符长度超过1字节后,会不断覆盖后续栈内存:

  • 输入4字符时,刚好覆盖token和部分delimiters的内存,还没触及栈帧的关键数据(比如返回地址、栈基指针),程序还能勉强运行;
  • 输入5字符及以上时,溢出的字符会覆盖栈帧的关键结构,触发GCC默认开启的栈溢出保护机制(-fstack-protector),程序直接被终止。

内容的提问来源于stack exchange,提问作者Stuart

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 11:17:45