最近将手头上负责的项目代码从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升级二三事的更多相关文章

  1. C++雾中风景番外篇:理解C++的复杂声明与声明解析

    在学习C系列语言的过程之中,理解C/C++的复杂声明一直是初学者很困扰的问题.笔者初学之时也深受困扰,对很多规则死记硬背.后续在阅读<C专家编程>之后,尝试在编译器的角度来理解C/C++的 ...

  2. C++雾中风景番外篇2:Gtest 与 Gmock,聊聊C++的单元测试

    正式工作之后,公司对于单元测试要求比较严格.(笔者之前比较懒,一般很少写完整的单测~~).作为一个合格的开发工程师,需要为所编写代码编写适量的单元测试是十分必要的,在实际进行的开发工作之中,TDD(T ...

  3. C++雾中风景番外篇3:GDB与Valgrind ,调试代码内存的工具

    写 C++的同学想必有太多和内存打交道的血泪经验了,常常被 C++的内存问题搅的焦头烂额.(写 core 的经验了)有很多同学一见到 core 就两眼一抹黑,不知所措了.笔者 入"坑&quo ...

  4. electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLint

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google ...

  5. 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  6. iOS冰与火之歌(番外篇) - 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权

    iOS冰与火之歌(番外篇) 基于PEGASUS(Trident三叉戟)的OS X 10.11.6本地提权 蒸米@阿里移动安全 0x00 序 这段时间最火的漏洞当属阿联酋的人权活动人士被apt攻击所使用 ...

  7. 给深度学习入门者的Python快速教程 - 番外篇之Python-OpenCV

    这次博客园的排版彻底残了..高清版请移步: https://zhuanlan.zhihu.com/p/24425116 本篇是前面两篇教程: 给深度学习入门者的Python快速教程 - 基础篇 给深度 ...

  8. 可视化(番外篇)——在Eclipse RCP中玩转OpenGL

    最近在看有关Eclipse RCP方面的东西,鉴于Gephi是使用opengl作为绘图引擎,所以,萌生了在Eclipse RCP下添加画布,使用opengl绘图的想法,网上有博文详细介绍这方面的内容, ...

  9. 可视化(番外篇)——SWT总结

    本篇主要介绍如何在SWT下构建一个应用,如何安装SWT Designer并破解已进行SWT的可视化编程,Display以及Shell为何物.有何用,SWT中的常用组件.面板容器以及事件模型等. 1.可 ...

随机推荐

  1. Java工程师的必备知识点

    最近参加了一次公司内部的调岗计划,打算加入一个更核心的部门.调岗计划有面试环节,为了不让自己搞砸,悉心准备了将近一个月,请教了百度和腾讯的有过面试官经验的大学同学,系统性的总结了Java工程师的核心知 ...

  2. MySQL的字段属性+SQLyog查看建表语句

    MySQL的字段属性 写在前面:数据库就是单纯的表,用来存储数据,只有行和列.行代表数据,列代表字段(id.name.age这种就叫字段) 1.长度 2.默认 3.主键 4.非空 5.Unsigned ...

  3. [Python]python对csv去除重复行 python 2020.2.11

    用pandas库的.drop_duplicates函数 代码如下: import shutil import pandas as pd frame=pd.read_csv('E:/bdbk.csv', ...

  4. javaweb基础备忘

    Request对象的主要方法有哪些 setAttribute(String name,Object):设置名字为name的request 的参数值 getAttribute(String name): ...

  5. Hibernate 和Mybatis的区别

    Hibernate 和Mybatis的区别   1.hibernate 入门门槛高,是一个标准的ORM框架(对象关系映射),不需要程序写sql,sql语句自动生成,对sql语句进行优化.修改比较困难. ...

  6. python requests [Errno 104] Connection reset by peer

    有个需求,数据库有个表有将近 几千条 url 记录,每条记录都是一个图片,我需要请求他们拿到每个图片存到本地.一开始我是这么写的(伪代码): import requests for url in ur ...

  7. [CF527D] Clique Problem - 贪心

    数轴上有n 个点,第i 个点的坐标为xi,权值为wi.两个点i,j之间存在一条边当且仅当 abs(xi-xj)>=wi+wj. 你需要求出这张图的最大团的点数. Solution 把每个点看作以 ...

  8. render(七)

    Vue 的 _render 方法是实例的一个私有方法,它用来把实例渲染成一个虚拟 Node.它的定义在 src/core/instance/render.js 文件中: Vue.prototype._ ...

  9. AntDesign(React)学习-15 组件定义、connect、interface

    虽然常用的编码用一种即可,但是看别人文档或者示例时,有的写法不熟悉的话看着很不习惯,整理几种实现同一功能的不同写法 1.Dva Connect与@Connect import React, { Pro ...

  10. Token:服务端身份验证的流行方案

    01- 身份认证 服务端提供资源给客户端,但是某些资源是有条件的.所以服务端要能够识别请求者的身份,然后再判断所请求的资源是否可以给请求者. token是一种身份验证的机制,初始时用户提交账号数据给服 ...