设为首页 加入收藏

TOP

C安全编码--预处理(三)
2014-07-19 23:04:21 来源: 作者: 【 】 浏览:193
Tags:安全 编码 处理

 

  运行结果:

  和函数不同,宏的执行可以是交错的,两个宏单独执行时无害,但是它们在同一个表达式中组合在一起时可能导致未定义的行为:

  代码3:

  #define F(x) (++operations, ++calls_to_F, 2 * x)

  #define G(x) (++operations, ++calls_to_G, x + 1)

  /*...*/

  y = F(x) + G(x);

  operations变量在同一个表达式中读取并修改了2次,因此按照某种顺序,可能会接收到错误的值

  解决方案:

  inline int f(int x) {

  ++operations;

  ++calls_to_f;

  return 2 * x;

  }

  inline int g(int x) {

  ++operations;

  ++calls_to_f;

  return 1 + x;

  }

  /*...*/

  y = f(x) + g(x);

  在宏参数名两边加上括号

  代码1:

  #define CUBE(I) (I * I * I)

  int a = 81 / CUBE(2 + 1)

  被展开为: int a = 81 / (2 + 1 * 2 + 1 * 2 + 1);

  解决方案:

  #define CUBE(I) ((I) * (I) * (I))

  int a = 81 / CUBE(2 + 1)

  例外:当替换文本中的参数名由逗号分隔时,不管实际参数如何复杂,不需要对宏参数加上括号,因为逗号操作符的优先级低于其他任何操作符

  #define FOO(a, b, c) bar(a, b, c)

  /*...*/

  FOO(arg1, arg2, arg3);

  宏替换列表应该加上括号

  宏替换列表应该加上括号,以保护表达式中所有优先级较低的操作符

  代码1:

  #define CUBE(X) (X) * (X) * (X)

  int i = 3;

  int a = 81 / CUBE(i);

  //被展开为: int a = 81 / i * i * i

  解决方案:

  #define CUBE(X) ((X) * (X) * (X))

  int i = 3;

  int a = 81 / CUBE(i);

  这个方案最好实现为内联函数

  应该使用typedef定义编码类型

  如果需要对类型进行编码,应该使用类型定义(typedef)而不是宏定义(#define)。类型定义遵循作用域规则,而宏定义却不遵循

  代码1:

  #define cstring char *

  cstring s1, s2;

  其中s1声明为char *,s2声明为char

  解决方案:

  typedef char * cstring;

  cstring s1, s2;

  不要复用标准头文件名

  如果一个文件与标准头文件同名。并且位于包含源文件的搜索路径中,其行为是未定义的

  建议:不要复用标准头文件名、系统特定的头文件名或其他的头文件名

  把头文件放在包含防护条件中

  防止头文件没多次包含或是忘记包含,通过一种简单的技巧:每个头文件应该用#define指令定义一个符号,表示已经被包含,然后整个头文件出现在一个包含防护条件中:

  #ifndef HEADER_H

  #define HEADER_H

  /*....header的内容*/

  #endif

  避免使用连续的问号

  两个连续的问号表示一个三字符序列,据C99标准,在一个源文件中,下列这些3个字符的连续出现被对应的单个字符所替换

=# )] !|
([ '^ >}
/\ <{ -~

  代码1:

  //what is the value of a now /

  a++;

  由于 /等价于\,a++相当于被注释掉

  解决方案:

  //what is the value of a now /

  a++;

  保证头文件名唯一

  文件名中只有前8个字符保证是唯一的

  文件名中的点号后面只有1个非数字字符

  文件名中字符的大小写并不保证是区分的

  代码1:

  #include

  #include “Library.h”

  #include "library.h"

  #include "utilities_math.h"

  #include "utilities_physics.h"

  #include "my_library.h"

  Library.h和library.h可能表示同一个文件,并不清楚utilities_math和utilities_physics能否进行区分

  解决方案:

  #include

  #include “Lib_main.h”

  #include "lib_2.h"

  #include "util_math.h"

  #include "util_physics.h"

  #include "my_library.h"

  不要用不安全的函数替换安全函数

  宏经常用于修补现有的代码,用一个标识符对另一个标识符进行全局替换,但是这种做法存在一些风险,当一个函数被一个不够安全的函数替换时,这种做法就显得特别的危险

  代码:

  #define vsnprintf(buf, size, fmt, list) \

  vsprintf(buf, fmt, list)

  vsprintf函数并不会检查边界,因此size参数将被丢弃,在使用不信任的数据的时候可能会导致潜在的缓冲区溢出问题

  解决方案:

  #include

  #ifndef __USE_ISOC99

  /* 重新实现 vsnprintf()*/

  #include "my_stdio.h"

  #endif

  在一个do-while循环中包装多条语句的宏

      

首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++和MATLAB混合编程-DLL 下一篇小心指针被delete两次

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·About - Redis (2025-12-26 08:20:56)
·Redis: A Comprehens (2025-12-26 08:20:53)
·Redis - The Real-ti (2025-12-26 08:20:50)
·Bash 脚本教程——Li (2025-12-26 07:53:35)
·实战篇!Linux shell (2025-12-26 07:53:32)