• 编码注意事项


    # 内存泄漏

    1、对动态内存的使用保持敬畏,一旦malloc过,free要谨记在心。

    尤其是对于多重提前return的函数,如:

     1 void func(void)
     2 {
     3     char *ptr = malloc(100);
     4     ...
     5     if (condition1) {
     6         ... // !!! 记得free
     7         return;
     8     }
     9     
    10     ...
    11     if (condition1) {
    12         ... // !!! 记得free
    13         return;
    14     }
    15     
    16     // !!! 记得free
    17 }

    2、减少动态内存的嵌套使用,如:

     1 struct item_ctx {
     2     char *ctx; // dynamic alloc
     3 }
     4 
     5 struct item {
     6     int item_desc;
     7     struct item_ctx *ctx; // dynamic alloc
     8 }
     9 
    10 struct queue {
    11     int size;
    12     struct item *data; // dynamic alloc
    13 }

    这里层层嵌套,使用完很容易漏掉某个地方的内存释放。

    3、釜底抽薪之策:尽量不用动态内存。

    比如,如果一项业务最大使用内存是知道的,就可以使用栈内存。如此,既避免了内存泄漏,又有效率方面的提升。

    4、智能指针

    # 死锁

    死锁的避免措施,在思想上和预防内存泄漏是一样的。重复一遍就是:

    1、lock/unlock成对出现

    2、避免锁的嵌套

    3、设计阶段,尽量避免锁的使用

    4、智能锁

    # for/while语句导致死循环

    这是一个比较容易忽视、一旦出现(尤其大型软件)很难排查的问题,一个简单示例:

    1 uint32_t g_counter;
    2 
    3 while (g_counter > 0) {
    4     g_counter --;
    5     ...
    6 }

    如果 g_counter 减到0的瞬间,又被外部某段代码减了一次,bug就这么发生了。

    # system()系统调用

    在使用system/popen执行系统命令的时候,注意参数可能带空格的情况,如:

    1 system("wpa_passphrase ssid passwd_1234");

    上述命令根据用户的WiFi热点"ssid"对明文密码"passwd_1234"进行加密,如果"ssid"带空格的话就悲剧了。

    解决措施:在构建命令的时候,记得用引号("")圈起来。

    # errno的误用

    一种常见的 errno 错误使用示例

    if (somecall() == -1) {
       printf("somecall() failed
    ");
       if (errno == ...) { ... }
    }

    errno 是一个全局变量,当 if (errno == ...) 的时候,errno 的值可能已经被其他代码修改掉了。

    正确的做法是,在 somecall() 调用异常时,尽快保存 errno 的值:

    if (somecall() == -1) {
       int errbk = errno;
       printf("somecall() failed
    ");
       if (errbk == ...) { ... }
    }

    # 宏定义使用

    1、宏定义时记得用括号()引起来。

    2、编码过程中如果修改了宏,一定要 rebuild (make clean;make)你的工程。

     # 使用变量前一定要初始化

    示例:

    char buffer[32];
    
    // 错误做法!!!
    strncpy(buffer, src, sizeof(buffer) - 1);
    
    // 正确做法
    memset(buffer, 0, sizeof(buffer));
    strncpy(buffer, src, sizeof(buffer) - 1);

     # 字节对齐

    涉及结构体成员大小的时候,注意字节对齐问题。如:

    struct msgq_data {
    	pid_t pid;
    	size_t len;
    }

    在 64 位系统上,pid_t 类型占 4 字节大小,size_t 类型占 8 字节大小,编译器按照 8 字节对齐,所以 pid 成员也是 8 字节大小。

    待续。。。

  • 相关阅读:
    用pelican搭建完美博客
    对比MySQL,什么场景MongoDB更适用
    客官,您的 Flask 全家桶请收好
    虚拟机安装macos 分辨率不正常修改不了,不能全屏如何解决
    mac开启HiDPI
    虚拟机安装MacOS|unlocker解锁出现闪退问题!
    下载com.vmware.fusion.tools.darwin.zip.tar慢
    VMware虚拟机安装黑苹果MacOS Mojave系统详细教程
    Python格式化输出
    ubuntu进入initramfs,系统黑屏
  • 原文地址:https://www.cnblogs.com/rockyching2009/p/12917317.html
Copyright © 2020-2023  润新知