C++项目中的各种坑【2017.10.30】
来源:互联网 发布:知乎手机端发表文章 编辑:程序博客网 时间:2024/05/22 00:55
C++项目中的各种坑
更新时间 2017.10.30
最近做C++项目的时候,踩了许多坑。想着如果能够将它们记录下来,整理在案,也算是不错的总结。于是写下此篇。
2017.10.30
for 循环的判断会重新计算
一个比较基础的问题了,但是不注意可能会踩坑。
int c = 8;for (int i = 0; i < c; i++) { c--;}
for 循环不会保存 c 的值,每次都要计算表达式 (i < c)。
所以如果在循环中修改了判断时引用的变量(或者判断时调用的函数是不纯的),那么需要警惕。(STL容器进行for循环时,判断 end() 恰巧利用了这一点。)
2017.10.19
Linux 下 printf 输出不正常 (内嵌汇编的坑)
在写 JitFFI 的时候,为了测试 long double 的传递特性,书写了下面的代码:
void print_ld(long double ld) { printf("%Lf\n", ld); printf("0x%llX\n", *(uint64_t*)&ld); printf("0x%llX\n", *((uint64_t*)&ld + 1));}void caller(void) { asm("sub $0x8, %rsp"); asm("push $0x3fff"); asm("mov $0x8000000000000000, %rax"); asm("push %rax"); asm("call print_ld"); asm("add $0x18, %rsp");}int main(void){ caller(); return 0;}
正常情况下,caller 函数如下书写:
void caller(){ print_ld(1.0);}
应该会输出
1.0000000x80000000000000000x3FFF
但是实际上是(本机测试结果):
0.0000000x80000000000000000x3fff
反汇编以后,对比内嵌汇编版本与正常版本,发现 main 的代码有点不一样:
正常版本:
sub $0x8, %rspcall callermov $0x0, eaxadd $0x8, %rspret
内嵌汇编于 caller 的版本:
call callermov $0x0, eaxret
因为x64要求在调用函数时,%rsp
与16字节对齐,所以调用 print_ld
函数时,内嵌版本会出现对齐错误。print_ld
调用 第一个 printf
时,错误才显现出来。
以上案例告诉我们,内嵌汇编不要随便写。。
2017.10.16
Linux 下死循环导致死机
重构代码的时候,重写了一个带有循环函数。测试时候出现死循环导致死机。
解决办法:
在没有把握的情况下,加上assert用于测试。
int JC = 0;while (true){ assert(JC++ > 100000);}
保存 std::initializer_list 导致引用失效
保存 std::initializer_list 可能会出现引用失效的问题。
错误示例如下:
class L{public: L(const std::initializer_list<int> &list) : list(list) {}private: std::initializer_list<int> list;}
解决办法:不保存std::initializer_list
隐式转换导致的各种数值错误
错误示例:
using byte = uint8_t;void print(byte v){ printf("%d\n", v);}print(233); // Error!
解决办法:
1. 重视 warning
2. 采取显式命名的方式:
void print_byte(byte v){ printf("%d\n", v);}
printf 输出参数不加 \n
printf 输出参数不加 \n
,大致有两种错误形式。
一种是两个参数混杂在一起,一种是在Linux下不能即时输出。
void print(int v){ printf("%d", v);}print(5);print(6); // Output : 56
这种混杂在一定情况下可能是我们希望看到的,但是大部分情况都会扰乱视听,消耗巨大时间排除bug.
- C++项目中的各种坑【2017.10.30】
- 各种杂项知识点与项目中的坑
- c语言中的各种printf
- eclipse中的项目导入到源生项目中的各种问题
- 产品项目生命周期中的各种文档
- web项目中的各种路径的获取
- C 项目中的extern "C" {}
- C语言中的各种修饰符
- c中的字符串的各种问题
- C语言中的各种进制转换
- Objective-C中的BOOL类型各种转换
- C语言中的各种输入函数整理
- C++项目中的extern "C" {}
- C++项目中的extern "C" {}
- C++项目中的extern "C" {}
- C++项目中的extern "C" {}
- C++项目中的extern "C" {}
- C++项目中的extern "C" {}
- 基于CentOS搭建Discuz
- JDK8中ThreadGroup源码解析
- teamviewer12,"未就绪,请检查您的连接"
- C++(11):OpenGL坐标系及绘制多个矩形
- make的-j命令(加速Linux程序编译)
- C++项目中的各种坑【2017.10.30】
- PPPoE的验证方法
- python中items()和iteritems()函数的用法
- 关于微信公众平台本地测试ip如何加入IP白名单
- 【快速幂 && 公式推导】LightOJ
- PHP常用函数总结(180多个)
- maven简介
- php怎样获取用户的所在城市
- javaweb获取用户真实ip