【Linux调试经验】编译时sscanf参数警告不可忽略

本人在为一款路由器写一个linux内核模块时遇到如下问题。

问题:
从一块内存buf中格式化字符到变量中,发现变量的值总是不正确。

发现:
写好的代码编译和链接能通过,运行就可能出错了。以前该模块写成后在交叉编译器mipsel-linux-gcc(版本:V3.4.2)下运行没问题,后来换成V4.6.3版本后编译,运行就不正确了。(其实代码本身就有问题,代码在mipsel-linux-gcc V4.3.2 下正常运行只是侥幸)

相关代码:

int16_t a, b, c, d;

sscanf(buf, "%d %d %d %d", &a, &b, &c, &d);
//其中buf = "192 168 16 1\n"

编译信息如下:

make -C /root/study/MTK3/MTK_source/linux-2.6.36.x M=/root/study/netfilter3/t1
make[1]: Entering directory `/root/study/MTK3/MTK_source/linux-2.6.36.x'
  LD      /root/study/netfilter3/t1/built-in.o
  CC [M]  /root/study/netfilter3/t1/flow_monitor.o
/root/study/netfilter3/t1/flow_monitor.c:274: warning: function declaration isn't a prototype
/root/study/netfilter3/t1/flow_monitor.c: In function `read_conf_ip':
/root/study/netfilter3/t1/flow_monitor.c:300: warning: int format, different type arg (arg 3)
/root/study/netfilter3/t1/flow_monitor.c:300: warning: int format, different type arg (arg 4)
/root/study/netfilter3/t1/flow_monitor.c:300: warning: int format, different type arg (arg 5)
/root/study/netfilter3/t1/flow_monitor.c:300: warning: int format, different type arg (arg 6)
  CC [M]  /root/study/netfilter3/t1/maclist.o
  CC [M]  /root/study/netfilter3/t1/iplist.o
  CC [M]  /root/study/netfilter3/t1/flow_proc.o
  LD [M]  /root/study/netfilter3/t1/flow_manage.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /root/study/netfilter3/t1/flow_manage.mod.o
  LD [M]  /root/study/netfilter3/t1/flow_manage.ko
make[1]: Leaving directory `/root/study/MTK3/MTK_source/linux-2.6.36.x'

注意以上警告信息说 flow_monitor.c 文件第300行的函数中第三、四、五、六个参数格式不对。对应行如下:

sscanf(buf, "%d %d %d %d", &a, &b, &c, &d);

其中变量a、b、c、d声明的是uint16_t 。由于编译时我总是忽略该警告,导致后来查找半天才解决。

诊断
sscanf等类似函数在格式化字符串时,制定了%d则默认目的地址大小是一个int型所占的空间大小。在我所用的开发板,cpu是32位,也即int类型占用4个字节地址空间,而变量a、b、c、d确是uint16_t 类型的。所以必然导致变量后面两个字节的空间被踩坏,且还因为大小端的问题, 导致读出数据错位且不正确。

原理详解(图文)

这里写图片描述

由上图可以看出,格式化后,变量a的值为0,这就是问题所在。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值