C语言socket接收文件的自定义recvfile_all函数异常原因排查
可能的故障原因如下:
- 文件打开模式错误:你当前使用
fopen(data->filename, "w")的文本模式打开文件,在Windows环境下会自动对换行符做转义转换,若接收的是二进制文件(图片、压缩包、可执行文件等)会直接导致文件内容损坏、大小异常。需要改为二进制写模式"wb"。 recvall函数存在隐性bug:你定义的变量n类型为size_t无符号整型,但系统recv的返回值是ssize_t有符号整型,当网络出错recv返回-1时,赋值给无符号变量会变成超大正数值,导致n == -1的错误判断永远不成立,错误处理逻辑完全失效,甚至会触发死循环。需要把n的类型改为ssize_t。- 内存管理问题:
- 函数内分配的
buffer未调用free释放,存在内存泄漏 - 未判断
realloc的返回值,若realloc失败返回NULL,会丢失原有buffer的地址造成泄漏,同时后续操作会触发空指针崩溃
- 函数内分配的
- 未处理写文件失败的情况:你直接忽略了
fwrite的返回值,若遇到磁盘满、权限不足等情况,fwrite实际写入的字节数会小于传入的数值,你直接减去期望接收的字节数会导致文件内容缺失但函数判断为接收成功。 - 字节序不兼容问题:如果你的
struct filedata是直接从网络上接收发送端传输的二进制数据,struct stat中的st_size、st_blksize都是多字节整数,若发送端和接收端字节序不一致(比如x86平台小端、嵌入式设备大端),会导致你拿到的文件总大小、分块大小数值完全错误,要么收不满数据要么触发死循环。 - 错误路径资源泄漏:当接收出错提前
return时,你没有关闭已经打开的FILE*文件指针,也没有释放buffer,会导致文件句柄泄漏,后续可能无法正常操作该文件。 st_blksize取值风险:如果struct filedata来自发送端,发送端的文件系统块大小和接收端可能不匹配,若该数值异常过大超过系统socket接收缓冲区上限,或者数值为0,都会导致接收逻辑异常。- 变量名冲突风险:你定义的局部变量
recv和系统socket接收函数recv()同名,会屏蔽全局的函数名,虽然当前代码没有直接调用系统recv,但后续修改代码时极易触发逻辑错误,建议重命名为recv_len之类的不冲突的名称。
内容的提问来源于stack exchange,提问作者senya247
相关产品推荐
相关产品推荐

