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;
}
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; //得到最大整数
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;
}
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
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
2
3