调用WinHttpReadData出现变量check周围栈损坏错误如何解决?
问题根因定位
- 最可能的直接触发点是
main.cpp中的gets_s(urlInput)调用不符合规范:C标准及微软实现的gets_s要求传入两个参数,第一个是缓冲区地址,第二个是缓冲区最大容量,你只传了一个参数,编译器会把栈上紧邻的随机值当做容量参数,一旦输入的URL长度超过200字节,就会发生缓冲区溢出,直接覆盖栈上urlInput后面存储的check变量的内存,触发栈损坏报错。当你把check改为堆分配时,溢出的栈数据可能破坏堆的控制结构,就会报堆损坏错误。 - 次要风险点:你调用
printf("%s", st.pszOutBuffer)时依赖字符串结束符判断结尾,如果接口返回的HTTP内容是二进制数据、或者没有\0结束符,printf会读越界,虽然这个场景下大多只会导致打印乱码,但极端情况也会触发内存访问异常。 - 潜在风险点:你代码中定义的
WinHttpSubtransport结构体中的lpOutBuffer指针未使用,若其他代码逻辑中误写了这个野指针,也会导致内存越界。
解决步骤
- 修正
gets_s调用:将gets_s(urlInput);改为gets_s(urlInput, sizeof(urlInput));,严格限制输入长度不超过缓冲区容量,从根源避免栈溢出。 - 修正打印逻辑:将
printf("%s", st.pszOutBuffer);改为printf("%.*s", (int)st.dwDownloaded, st.pszOutBuffer);,按实际读取到的字节数打印内容,不依赖字符串结束符,避免读越界。 - 补全句柄校验逻辑:在调用
WinHttpQueryDataAvailable前增加对st.session、st.connect、st.request三个句柄的非空校验,避免无效句柄导致API异常写入内存。 - 若仍有报错,可临时注释HTTP读取和打印的全部逻辑,只保留输入URL的代码测试,如果不再报错即可确认问题完全由输入缓冲区溢出导致。
关于全局变量的疑问
你不需要参考官方示例使用全局变量,官方示例用全局变量只是为了简化演示代码,和你当前遇到的内存损坏问题没有关联。
内容的提问来源于stack exchange,提问作者Guy Sadoun
相关产品推荐
相关产品推荐

