红联Linux门户
Linux帮助

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

发布时间:2017-03-13 10:26:21来源:linux网站作者:arvik
本人在为一款路由器写一个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 类型的。所以必然导致变量后面两个字节的空间被踩坏,且还因为大小端的问题, 导致读出数据错位且不正确。
 
原理详解(图文)
【Linux调试经验】编译时sscanf参数警告不可忽略
由上图可以看出,格式化后,变量a的值为0,这就是问题所在。
 
本文永久更新地址:http://www.linuxdiyf.com/linux/29131.html