记录一些比较难解决,需要查资料思考,第一眼看不出的bug
C
环境:Ubuntu 16.04
编译器:GCC
goto语句标签之间的区域不能存在声明语句
用C语言在Linux上写轮询的时候,遇见的err。
block.c: In function ‘main’:
block.c:20:5: error: a label can only be part of a statement and a declaration is not a statement
char buf[20];
^
block.c:21:5: error: expected expression before ‘int’
int len = read(fd, buf, 20);
^
block.c:22:9: error: ‘len’ undeclared (first use in this function)
if (len < 0)
^
block.c:22:9: note: each undeclared identifier is reported only once for each function it appears in
err中特别提到了:
a label can only be part of a statement and a declaration is not a statement
于是我试着将所有在goto标签之间的声明全部移除去,结果编译通过了。之后又实验了一下,也是如此。
解决方法: 将所有在goto标签之间的声明全部移除到标签之外。
C++
构造函数初始化列表初始化先后顺序导致的问题
环境:Ubuntu 16.04
编译器: g++
数据成员定义先后顺序为:
构造函数初始化列表:
ERR:
产生原因:主要原因为系统内存,无法满足程序内存分配需求。
解决:
起初这个让人非常疑惑,我根本没有分配多大内存,怎么会导致系统内存不够用呢?
困扰了我许久之后。我在每个分配内存的地方都用cout打印一个信息观察从那个地方开始出现问题。
定位到出问题最开始处,源码如下:
显然必定是构造函数分配内存时出现了问题,分配了一个系统无法接下的内存量。
构造函数内存分配代码如下:
看到这里的一瞬间我明白了,一定是类中参数定义的先后顺序问题。_pstr成员先于_size成员一不在类中定义。初始化列表中会根据类中成员数据定义的先后顺序进行初始化,那么_size应该是被编译器设置为0xCCCCCCCCCCCCCC总之全部填充C。这不得了,这个内存就太惊人了。我记得Linux似乎只是利用了64系统的48位寻址。
一个关于移动语义导致问题的思考。
环境:Ubuntu 16.04
编译器: g++
报错:
Error in `./a.out’: double free or corruption (fasttop): 0x00000000019750b0
此处毫无疑问是多次释放同一块内存,最终定位到此处。
多次释放内存在我的经验中,有时候将弃用指针置空可能会观察到其他现象,但这里直接就不报错了,不清楚为什么这样,如下:
于是我我想问题可能出在std::move的实现上,所以跟进查看std::move源码,并且在我的印象中std::move应该是强制类型转换,将目标强制转为右值,并不在建议使用。
查阅std::move源码如下:
可以看见,如果目标类型有reference属性,则摘除并使用static_cast强制转换为去引用类型的右值。并且这里可以知道并没有调用任何其他函数。
仔细思考后,突然想通了。感叹自己实在太笨,std::move中的确是强制转换也没有调用其他函数释放目标,但是rhs._pstr的值并不一定改变了变为了野指针,那么rhs很有可能会调用自己的析构函(实现为_pstr非空delete)数释放rhs._pstr指向的堆内存,现在rhs._pstr自己指向的堆空间交给this._pstr,this同样会调用自己的析构函数那么就造成了多次delete同一块内存。