C++雾中风景番外篇4:GCC升级二三事
最近将手头上负责的项目代码从GCC 4.8.2升级到了GCC 8.2。(终于可以使用C++17了,想想后续的开发也是很美好啊~~)不过这个过程之中也遇到了一些稀奇古怪的问题,在这里做一个简单的记录,希望后续有同学遇到类似的问题能作为参考。
1. error: unable to find string literal operator 'operator"
这个我感觉是历史的遗留问题了,从C++11开始就不支持字符串字面量后面直接连接变量名,GCC 4.8.2应该是没有支持该编译检查,所以后续升级8.2的时候报了类似的错误。
听着有些抽象啊,举个栗子:
#define LOG(fmt, ...) printf("[%s][%s][%d]:"fmt "\n", __FILE__, __FUNCTION__,\
__LINE__, ##__VA_ARGS__)
上面是一段C++常用的日志宏定义,在宏定义展开的时候,编译器会默认将[%s][%s][%d]:,fmt,"\n"字面量拼接在一起,然后和后面行号等宏定义作为参赛打印出来。
#define LOG(fmt, ...) printf("[%s][%s][%d]:" fmt "\n", __FILE__, __FUNCTION__,\
__LINE__, ##__VA_ARGS__)
2. error: flexible array member not at end of struct
在C++之中,给定了一个结构定义和一个指向结构的指针,编译器必须能够通过指针偏移的方式访问该结构的任何成员。由于结构中每个成员的位置都取决于其前导成员的数量和类型,因此访问任何结构都需要知道所有前导成员的数量和类型。
在结构体之中,如果是数组为结构体之中最后的成员。这并不违反上述的编译规则。但是,如果flexible array member出现在了结构体末尾以外的任何位置,则其后的任意成员的位置都将取决于数组中对应的类型的个数,所以编译器禁止将没有定义长度的数组作为结构体的中间成员。
举个栗子:
struct S {
int a;
char b[];
int c;
};
这里由于b成员的长度是不确定的,所以编译器无法通过S的指针推断出成员c的位置,所以编译报错:

而我们看如下的结构体就没有编译报错的问题了:
struct S {
int a;
int c;
char d[];
};
看到这,可能有些读者会问了,如果我就是需要在结构体之中定义两个变长的数组,能怎么办呢? 笔者有觉得有下面两种方式实现:
- 用指针啊!!!把结构定义为下面这种形式就可以了
struct S {
int a;
char b[0];
int c;
char d[];
};
- 如果b和d成员长度一致或者不在内存损耗的情况,也可以采用如下方式来定义这个结构体:
struct Pair {
char b;
char d;
}
struct S {
int a;
int c;
Pair p[];
};
3. 返回值的坑
有返回值的函数没有指定return,或是return了却没有给出返回值在gcc进行-O优化等级大于1时,会出现各种稀奇古怪的core。笔者也是通过GDB调试了很久,最终通过编译器的警告发现了上述的问题。
这个理论上是一个很低级的错误,但是笔者花了比较长的时间排查,因为出现的实在是有些诡异。
我们来看如下代码:
int test(int a, int b) {
auto c = a + b;
}
int main() {
auto c = test(10, 20);
return 0;
}
上面我们可以看到test函数本身是需要返回一个int类似作为返回值的,但是这里并没有进行应有的返回。
上述代码在GCC 4.8.2之中并不会出现问题,但是一旦切换到GCC8.2之后,并且在编译优化等级大于1的时候,就会core在这个函数的执行代码位置。
所以为了规避上述的问题,笔者这里推荐使用GCC编译时开启编译选项:-Werror=return-type。这样,有上述返回值问题的代码就会在编译期间被编译器识别并报错。(其实参数-W,-Wall编译器是会对上述问题报警的,但是warning嘛,大家经常就不care啊~~~)
4.小结
简单总结了一下笔者升级GCC过程之中遇到的一些小的编译问题,希望可以帮助到同样问题的同学。GCC8.2也囊括了绝大多数C++17的新特性和部分的C++2a的特性,各种新的语法糖在编码过程之中也能极大的提高开发效率。Enjoy your modern CPP。
C++雾中风景番外篇4:GCC升级二三事的更多相关文章
- C++雾中风景番外篇:理解C++的复杂声明与声明解析
在学习C系列语言的过程之中,理解C/C++的复杂声明一直是初学者很困扰的问题.笔者初学之时也深受困扰,对很多规则死记硬背.后续在阅读<C专家编程>之后,尝试在编译器的角度来理解C/C++的 ...
- C++雾中风景番外篇2:Gtest 与 Gmock,聊聊C++的单元测试
正式工作之后,公司对于单元测试要求比较严格.(笔者之前比较懒,一般很少写完整的单测~~).作为一个合格的开发工程师,需要为所编写代码编写适量的单元测试是十分必要的,在实际进行的开发工作之中,TDD(T ...
- C++雾中风景番外篇3:GDB与Valgrind ,调试代码内存的工具
写 C++的同学想必有太多和内存打交道的血泪经验了,常常被 C++的内存问题搅的焦头烂额.(写 core 的经验了)有很多同学一见到 core 就两眼一抹黑,不知所措了.笔者 入"坑&quo ...
- electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLint
我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google ...
- 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- iOS冰与火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权
iOS冰与火之歌(番外篇) 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权 蒸米@阿里移动安全 0x00 序 这段时间最火的漏洞当属阿联酋的人权活动人士被apt攻击所使用 ...
- 给深度学习入门者的Python快速教程 - 番外篇之Python-OpenCV
这次博客园的排版彻底残了..高清版请移步: https://zhuanlan.zhihu.com/p/24425116 本篇是前面两篇教程: 给深度学习入门者的Python快速教程 - 基础篇 给深度 ...
- 可视化(番外篇)——在Eclipse RCP中玩转OpenGL
最近在看有关Eclipse RCP方面的东西,鉴于Gephi是使用opengl作为绘图引擎,所以,萌生了在Eclipse RCP下添加画布,使用opengl绘图的想法,网上有博文详细介绍这方面的内容, ...
- 可视化(番外篇)——SWT总结
本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物.有何用,SWT中的常用组件.面板容器以及事件模型等. 1.可 ...
随机推荐
- 小白月赛22 D : 收集纸片
D:收集纸片 考察点 : 全排列,对数据范围的估计程度 坑点 : 注意算最后回到初始的那步距离 析题得侃 : 一看题目最短路,诶呦,这不是最拿手的 BFS 走最短路吗?哈哈,定睛一看 这么多目的地,这 ...
- vue router的嵌套使用与传值的query方式
嵌套路由 当我们不满足与 /home这种路由,而是希望通过 /home/news和/home/message访问一些内内容 那么就需要嵌套路由了 实现嵌套路由有两个步骤: ·创建对应的子组件,并且在路 ...
- UVA122 二叉树的层次遍历
题目链接 https://vjudge.net/problem/UVA-122 #include<bits/stdc++.h> using namespace std; #define l ...
- 【已解决】使用 yarn 安装时,报错node_modules\node sass:Command failed.
npm install -g mirror-config-china --registry=http://registry.npm.taobao.org npm install node-sass y ...
- scanf使用尿性
scanf("xxx%d",&xx); "xxxx%d" 这里不能乱写,这里是标准输入,不然xx的一直不对,和printf不一样,而且%d 和& ...
- ACWing 238 银河英雄传说
最近带权并查集这块比较薄弱,直接看食物链看不懂,就老实一步步来了. 有一个划分为N列的星际战场,各列依次编号为1,2,…,N. 有N艘战舰,也依次编号为1,2,…,N,其中第i号战舰处于第i列. 有T ...
- yii csrf 配置
csrf默认启用 全局配置 'components'=>array( 'request'=>array( // Enable Yii Validate CSRF Token 'enable ...
- python的selenium实现自动登陆
知道思想,参考其他文档,python的request模块和selenium模块都可以实现get_cookie()和 add_cookie()的功能. 由于现在在学习selenium自动化测试,我选用s ...
- 解决PHP Redis扩展无法加载的问题
最近在工作中需要使用PHP访问Redis,从https://github.com/phpredis/phpredis下载了phpredis,并且按照官方的说明进行了安装 phpize ./config ...
- 解决pycharm创建github工程但push失败的问题
1.运行git-cmd.exe; 2.d: cd 工程路径 3.执行命令:git remote set-url origin https://github.com/wawj901124/jmet ...