gcc编译宏展开观察
复杂宏编译期展开后是什么样的?当编译宏报错时,如何差错?
例子
编译一个修改后PostgreSQL源码,elog宏原型为:
- snippet.c
#define elog(elevel, ...) \ do { \ pg_prevent_errno_in_scope(); \ elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \ elog_finish(elevel, __VA_ARGS__); \ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ pg_unreachable(); \ } while(0)
修改后:
- snippet.c
#define elog(elevel, ...) \ do { \ if (no_report) \ break; \ pg_prevent_errno_in_scope(); \ elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \ elog_finish(elevel, __VA_ARGS__); \ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ pg_unreachable(); \ } while(0)
注意,新增了两行。
编译报错。
[yz@test-4 src]$ VERBOSE=1 make -j1 …… [ 11%] Building C object src/backend/CMakeFiles/libpostgresql.dir/access/aocs/aocsam_handler.c.o cd /opt2/yz/Debug/src/backend && env CCACHE_DIR="/home/yz/.ccache_postgresql_Debug" /usr/bin/ccache /opt/rh/devtoolset-8/root/usr/bin/gcc -DBOOST_DATE_TIME_POSIX_TIME_STD_CONFIG -DDLSUFFIX=\".so\" -DENABLE_SSL -DENABLE_VE -DOS_LINUX -DPGXC=1 -DUSE_CMAKE -DUSE_CUR L -DUSE_OPENSSL -DXCP=1 -I/opt2/yz/src/include -I/opt2/yz/src/include/snowball -I/opt2/yz/src/include/snowball/libstemmer -I/opt2/yz/src/interfaces/libpq -D_GNU_SOURCE -fno-strict-aliasing -fwrapv -Wno-unknown-pragmas -Wno-format-truncation -Wno-stringop-truncation -msse4.1 -msse4.2 -mpopcnt -DFAKE_GB18030 -DTRACE_SORT -DWAL_DEBUG -DCACHEDEBUG -g -Werror -Wall -std=gnu11 -o CMakeFiles/libpostgresql.dir/access/aocs/aocsam_handler.c.o -c /opt2/yz/src/backend/access/aocs/aocsam_handler.c/opt2/yz/src/backend/access/aocs/aocsam_handler.c: In function ‘aocsam_parallelscan_estimate’: /opt2/yz/src/backend/access/aocs/aocsam_handler.c:593:1: error: control reaches end of non-void function [-Werror=return-type] }
排查问题
我们想知道以上宏展开后是什么样子,可以这样:
[yz@test-4 backend]$ cd /opt2/yz/Debug/src/backend && env CCACHE_DIR="/home/yz/.ccache_postgresql_Debug" /usr/bin/ccache /opt/rh/devtoolset-8/root/usr/bin/gcc -DBOOST_DATE_TIME_POSIX_TIME_STD_CONFIG -DDLSUFFIX=\".so\" -DENABLE_SSL -DENABLE_VE -DOS_LINUX -DPGXC=1 -DUSE_CMAKE -DUSE_CURL -DUSE_OPENSSL -DXCP=1 -I/opt2/yz/src/include -I/opt2/yz/src/include/snowball -I/opt2/yz/src/include/snowball/libstemmer -I/opt2/yz/src/interfaces/libpq -I/opt2/yz/src/backend/src/PG_Glue/include -isystem -D_GNU_SOURCE -fno-strict-aliasing -fwrapv -Wno-unknown-pragmas -Wno-format-truncation -Wno-stringop-truncation -msse4.1 -msse4.2 -mpopcnt -DFAKE_GB18030 -DTRACE_SORT -DWAL_DEBUG -DCACHEDEBUG -g -Werror -Wall -std=gnu11 -o /tmp/aocsam_handler.c -E /opt2/yz/src/backend/access/aocs/aocsam_handler.c
然后,我们打开/tmp/aocsam_handler.c文件,查看宏展开后的代码:
- snippet.c
static Size aocsam_parallelscan_estimate(Relation rel) { do { if (no_report) break; int __errno_location __attribute__((unused)); elog_start("/opt2/yz/src/backend/access/aocs/aocsam_handler.c", 592, __func__); elog_finish(20, "parallel SeqScan not implemented for scolumn tables"); if (__builtin_const ant_p(20) && (20) >= 20) abort(); } while(0);}
打赏作者以资鼓励: