Colderleo's blog Colderleo's blog
首页
Linux
C++
Python
前端
工具软件
mysql
索引
关于
GitHub (opens new window)

Colder Leo

热爱代码的打工人
首页
Linux
C++
Python
前端
工具软件
mysql
索引
关于
GitHub (opens new window)
  • bug定位的一些情形
    • c++性能调优,可能的情况
    • total-编程知识点集锦
    • hpc_common.hpp
    • memory order 内存模型
    • 类型推导之auto-template-decltype
    • 完美转发forward源码分析
    • 左值和右值,右值引用、重载 std-move,引用折叠
    • cmake用法
    • alignas、alignof、sizeof实现内存对齐分配
    • 通过宏定义控制debug打印
    • 程序耗时性能测试
    • 线程池开源项目阅读
    • C++类中包含没有默认构造函数的成员
    • C++可变参数模板
    • C++属性继承 public protected private
    • C++智能指针
    • C++导出so的方法,以及extern C 注意事项
    • 四种spin lock
    • condition_variable和unique_lock
    • dpdk、kernel bypass
    • 智能网卡solarflare、Mellanox、X10等
    • 汇编寄存器和常见指令
    • c++ 类的静态成员变量未定义
    • C++获取类成员函数地址
    • preload示例
    • C++异常安全和RAII
    • C++11单例模式
    • C++歪门邪道
    • boost-program-option用法
    • c++17通过模板获取类成员的个数
    • 通过模板实现结构体成员拷贝-按成员名匹配
    • STL学习路径
    • boost库安装使用方法
    • C++文件读写
    • linux下socket通信demo,server和client
    • makefile写法
    • RxCpp
    • C++
    gaoliu
    2021-11-28
    目录

    bug定位的一些情形

    # 链表结尾结点的next应置为NULL

    参考: https://leetcode-cn.com/problems/merge-k-sorted-lists/ (opens new window)

    给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中,返回合并后的链表。

    可能出现的bug: 将链表节点重新连接后,需注意重组后的链表,其最后的结点的next应该置为NULL。

        //这种方法复杂度为nklognk, 不好
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            ListNode head(0);
            auto comp = [](ListNode* const a, ListNode* const b){return a->val > b->val;};
            priority_queue<ListNode*, vector<ListNode*>, decltype(comp)> q(comp);
            for(auto &tmp : lists) {
                while(tmp) {
                    q.push(tmp);
                    tmp = tmp->next;
                }
            }
            auto p = &head;
            while(!q.empty()) {
                p->next = q.top();
                p = p->next;
                q.pop();
            }
            p->next = nullptr; //这里将结尾的next置为NULL
            return head.next;
        }
    
        // 这种方法复杂度为nlogk, 好很多
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            auto head = ListNode(0);
            auto comp = [](ListNode* const &a, ListNode* const &b){return a->val > b->val;};
            priority_queue<ListNode*, vector<ListNode*>, decltype(comp)> q(comp);
            for (auto &h : lists) if (h != nullptr) q.push(h);
            auto p = &head;
            while (!q.empty()) {
                p->next = q.top();
                p = p->next;
                q.pop();
                if (p->next != nullptr) q.push(p->next);
            }
            return head.next;
        }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37

    # this指针被改写--数组index为负数,修改栈内存

    当数组的index为一个错误的负数时,此时修改其对应的值,可能会修改栈上的内存数据,导致一些奇怪的错误。

    # 链表中插入已有结点

    当向链表中插入结点时,如果该结点已经存在于链表中(而自己不知道,以为是新结点),重复的插入会导致链表出现循环等奇怪错误。

    # 移位操作64位数指明LL,以及移位优先级低于加减需要带括号

    64位整形最好显示的指明LL或ULL

    //移位操作时,64位整形数字在移位前必须显示加上LL或者ULL
    uint64_t m = 1<<63;
    cout<<m<<endl; //可能输出0或者 1<<31 的结果,取决于编译器
    
    uint64_t n = 1ULL<<63;
    cout<<n<<endl; //输出预期的1左移63位的结果,9223372036854775808
    
    //移位操作优先级低于加减
    int int_max = 1<<31 - 1;    //错误,先算31-1
    int int_max = (1<<31) - 1;    //得到最大整数
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    # 字符数组已满时作为 char * 字符串传参

    当字符数组满了并且末尾不为0时,其可能是正常的, 但是作为参数传入函数里面后,就不正常了。

    # tcpreplay-edit -E

    replay的包不对时,加-E和不加-E都试试,可能问题就在这里 -E, --efcs Remove Ethernet checksums (FCS) from end of frames

    # 函数局部变量和外部变量重名

    在将一段代码放进某个函数中时,直接剪切进去,可能会导致定义的某个变量本来定义在外面,现在定义在了函数里面(函数栈上),然后在外面使用该变量时出现错误。

    # 有返回值的函数没写return时 O1优化产生core,O0不产生Core

    在编译选项中增加 -Werror=return-type 可以让编译器对其强制报错。

    # c++11 中,class内部的static constexpr常量传给std::max时链接报错

    #include<iostream>
    using namespace std;
    class Foo {
        public: static constexpr int m = 5;
    }
    int main() {
        cout<<std::max(Foo::m, 3)<<endl;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

    链接报错,undefined reference Foo::m, 原因是std::max(var1,var2)传入的是引用,编译时编译器并没有尝试推导Foo::m的值,因此将其作为一个变量传入std::max。然鹅Foo::m是一个编译器常量,类似于宏定义#define Foo::m 3,并不存在变量符号,因此链接报错。

    c++14也会报错,c++17不报错,gcc版本8.3

    # c++11 class内使用lambda表达式,引用捕获,如果class类成员变量为匿名union,则可能导致奇怪的结果。

    某个程序某个类的成员函数中,用了lambda表达式且捕获了匿名union成员后程序会core,不用的话可以正常运行。

    未必是lambda的问题,但是去掉lambda后正常了。

    后来找到另一个原因: 模板类中的匿名union成员不会执行构造函数,但是编译也不警告或报错。

    # char型变量转成uint带符号变为反码,因此在处理字节的时候,最好用uint8_t

    #include <iostream>
    #include <unistd.h>
    #include <stdio.h>
    #include <string>
    
    inline static uint16_t htons_withbug(char *data) {
        printf("((uint16_t)data[0] << 8 = 0x%x\n", (uint16_t)data[0] << 8);
        printf("data[1] = 0x%x\n", (uint16_t)data[1]); //这里0xdc转uint16_t后,得到0xffdc
        return ((uint16_t)data[0] << 8) + (uint16_t)data[1];
    }
    
    int main()
    {
        char data[2] = {0x01, 0xdc};
        auto ret = htons_withbug(data);
        printf("ret = 0x%x\n", ret);
    }
    
    // g++ test_local.cpp -std=c++11
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    输出:

    ((uint16_t)data[0] << 8 = 0x100
    data[1] = 0xffdc
    ret = 0xdc
    
    1
    2
    3
    编辑 (opens new window)
    上次更新: 2023/05/07, 17:27:54
    c++性能调优,可能的情况

    c++性能调优,可能的情况→

    最近更新
    01
    通过模板实现结构体成员拷贝-按成员名匹配
    05-07
    02
    c++17通过模板获取类成员的个数
    05-01
    03
    avx-sse切换惩罚
    04-30
    更多文章>
    Theme by Vdoing | Copyright © 2019-2023 Colder Leo | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式
    ×