常犯的错误

来源:互联网 发布:二手房网络端口 编辑:程序博客网 时间:2024/04/26 07:40

1.结构体成员顺序发生变化引发的错误。

 

struct s{     int l;     char* p;}; int main(int argc, char* argv[]){    struct s s1 = {4, "abcd"};   //使用struct s s1 = {.l = 4, .p = "abcd"};更好,不怕顺序发生变化    return 0;}

 

2.结构体的大小变化引发的错误。

 

struct base{    int n;}; struct s{    struct base b;    int m;};

 

这个是在c语言中实现集成的基本手法。但是,假设第一个结构是第三方提供的,第二个是自己的。第三方的库以DLL的方式分发的,DLL最大好处在于可以独立替换。但是随着软件的进化,会出问题。

假如第三方在第一个结构中增加了一个新的成员int k;编译好后给了给了作者,然后我们直接替换……结构体的内存出现覆盖了……

唯一解决的办法就是重新编译全部代码。

 

3.在函数参数前加const

加上const修饰符,知识给编译器做类型检查使用,编译器禁止修改这样的变量。但这并不是强制的,我们可以用强制类型转换绕过去,一般不会出错……,但是,对于全局常量和字符串,用强制类型转换绕过去,运行时仍然会出错。原因在于它们是放在.rodata里面的,而.rodata内存页面时不能修改的。试图对它们修改,会引发内存错误。

 

int main(int argc, char* argv[]){     char* p = "abcd";     *p = '1'; return 0;}

 

4.重名符号

无论是函数名还是变量名,如果在不同的作用范围内重名,自然没有问题。但如果两个符号的作用域有交集,如全局变量和局部变量,全局变量与全局变量之间,重名的现象一定要坚决避免。gcc有一些隐式的规则来决定处理同名变量的方式,编译时可能没有任何警告和错误,但结果通常并非期望的……

 

5.栈溢出

在PC上,普通线程的占空间有十几M,通常够用了,定义大一点的临时变量没有问题,但是,在嵌入式环境中,线程的栈空间可能只有5k大小,甚至小到只有256个字节。这样的平台中,栈溢出很长见了吧……编程时应该注意栈溢出的可能,尤其是接近底层的时候。

 

6.使用sizeof

注意,传递数组的时候,数组退化为指针,用sizeof是无法取得数组大小的。

 

7.字节对齐

注意,不同类型的变量之间转换时要小心,如把char*强制转换为int*时,要格外小心。很可能在取出来以后,是错误的数据。还有字节对齐也会影响结构体的大小。不同机器之间传递数据时,在通信协议中要规定对齐的方式,避免对齐方式不一致引发的问题。

 

8.字节顺序

大端模式,小端模式……在网络通信和数据交换 有关软件中,字节序的问题需要特殊注意。


9.多线程共享变量中应该使用valotile修饰

关键字valotile的作用是告诉编译器,不要把变量优化到寄存器里。在开发多线程并发的软件时,如果这些线程共享一些全局变量,这些全局变量最好用valotile修饰。这样可以避免因为编译器优化而引起的错误,这样的错误非常难查!!

 

10.忘记函数的返回值

函数需要返回值,如果忘记使用return语句,它仍然会返回一个值,因为在i386上,EAX用来保存返回值,如果没有明确返回,EAX最后的内容被返回,所以EAX的内容是随机的。

0 0
原创粉丝点击