• 宏定义天坑记录


    宏定义天坑记录

    事件原委与推理过程

    在编译一个使用了Protobuf的项目时出现了如下报错

    [yb@VM-8-7-centos boost_searcher]$ make
    g++ -o http_server http_server.cc data/raw_html.pb.cc -std=c++11 -lboost_system -lboost_filesystem -lpthread -ljsoncpp -lprotobuf 
    In file included from /usr/local/protobuf/include/google/protobuf/io/coded_stream.h:132,
                     from data/raw_html.pb.h:23,
                     from index.hpp:11,
                     from searcher.hpp:10,
                     from http_server.cc:43:
    /usr/local/protobuf/include/google/protobuf/io/coded_stream.h: In member function 'std::ptrdiff_t google::protobuf::io::EpsCopyOutputStream::GetSize(uint8_t*) const':
    /usr/local/protobuf/include/google/protobuf/io/coded_stream.h:835:5: error: 'LOGLEVEL_4' is not a member of 'google::protobuf'; did you mean 'LOGLEVEL_INFO'?
      835 |     GOOGLE_DCHECK(ptr <= end_ + kSlopBytes);  // NOLINT
          |     ^~~~~~~~~~~~~
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    大致意思就是LOGLEVEL_3这玩意没被定义过,非常莫名奇妙的错误

    当发现是google/protobuf下的头文件的问题,直接就头大了

    编译过程中的语法错误就是两个极端,

    • 要么是自己的代码有语法错误,改一下就行
    • 但这是官方头文件文件报的语法错误啊,错误肯定不可能出现在人家,又不能调试,那没点时间和运气,这问题怕是搞不定

    但我多少是有点运气在的,无意间交换了源代码中的两个头文件,居然编译过了!!!!

    发现只要"searcher.hpp"定义在"HttpServer.hpp"前面,就能编过

    啊,这就有点玄幻了啊

    思考一下,这两个头文件内,应该是有某些依赖关系,或者跟编译的顺序有关

    试了一下

    这样也能过

    也就是说,searcher.hpp中一定有某些东西要出现在HttpServer.hpp前面

    又瞅了一眼报错

    既然报错从你来,就拎着你测吧(整个头文件包含树中,这个文件处于末梢,再向末梢就是官方文件了)

    放这里,诶果然又能编过了

    接下来,就拿它沿着整条头文件包含树,一直向下试,看哪里出现了问题

    直到到达一个log.hpp的头文件,不能再向下时

    发现,当raw_html.pb.hFATAL上时能编译过,在其下面则无法编过

    啊,小东西,终于找到你了啊

    如果你观察仔细,发现这个3,在前面的报错里也有点端倪

    当把这个宏定义为4时,果然变成了LOGLEVEL_4

    原因分析

    从上面推理中可以看出,显然是这个宏定义的问题

    google/protobuf的头文件中一定也有一个FATAL宏的定义,或者出现了FATAL关键词

    由于C语言对宏的处理发生在预处理阶段,只进行简单无脑的文本替换

    在所有的头文件中,我们都写了#pragma once,也就意味着在整个头文件包含体系中,只要出现第一次FATAL的宏定义,那以后的所有FATAL宏定义都将被忽视,一些不该被进行宏替换的地方也会被替换

    自然,当我们把google/protobuf的头文件放在我们的FATAL之前,也就不会受我们的宏定义影响

    总结

    虽然某些时候,对宏的使用能让我们的代码简单玄妙不少,但坑也是真的坑啊

    有了上面的经验教训,宏这种东西以后还是尽量少用了,毕竟不是每次都这么好运气

    如果替换宏的话,大家可以尝试使用conststatic const或者枚举的语法

  • 相关阅读:
    FIX三天日记-FIX简介
    js 取整,保留2位小数
    CSS学习————背景属性(4)
    四、Arthas
    高性能 低功耗Cortex-A53核心板 | i.MX8M Mini
    FL Studio21功能测评水果FL音乐制作数字音频工作站
    TikTok是不是正在改变数字营销的未来?
    VS 2019报错无法打开源文件
    JD的使用方法详情API 返回值说明
    【HBZ分享】TCP可靠性传输如何保证的?以及传输优化之Nagle算法
  • 原文地址:https://blog.csdn.net/yue152152/article/details/132766995