如何告知GCC某指针非空以消除memset的-Wnonnull警告?
消除OPN2_Reset函数中memset的非空编译警告
问题场景
现有一段包含OPN2_Reset函数的代码:
void OPN2_Reset(ym3438_t *chip, Bit32u rate, Bit32u clock) { Bit32u i, rateratio; rateratio = (Bit32u)chip->rateratio; memset(chip, 0, sizeof(ym3438_t)); ... }
编译时触发非空警告:
In function ‘void* memset(void*, int, size_t)’, inlined from ‘void Ym2612_NukedImpl::OPN2_Reset(ym3438_t*, Bit32u, Bit32u)’ at /home/logiclrd/zdoom/zmusic_build/zmusic/thirdparty/game-music-emu/gme/Ym2612_Nuked.cpp:1413:11, inlined from ‘void Ym2612_Nuked_Emu::reset()’ at /home/logiclrd/zdoom/zmusic_build/zmusic/thirdparty/game-music-emu/gme/Ym2612_Nuked.cpp:1842:45: /usr/include/x86_64-linux-gnu/bits/string_fortified.h:59:33: warning: argument 1 null where non-null expected [-Wnonnull] 59 | return __builtin___memset_chk (__dest, __ch, __len, | ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ 60 | __glibc_objsize0 (__dest)); | ~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/include/x86_64-linux-gnu/bits/string_fortified.h:59:33: note: in a call to built-in function ‘void* __builtin_memset(void*, int, long unsigned int)’
尝试过以下方法但均无效:
// 无效 if (chip != NULL) memset(chip, 0, sizeof(ym3438_t)); // 无效 ym3438_t tmp; ym3438_t *chip_nonnull = &tmp; if (chip != NULL) chip_nonnull = chip; memset(chip_nonnull, 0, sizeof(ym3438_t)); // 无效 assert(chip != NULL); memset(chip, 0, sizeof(ym3438_t));
有效解决方案
1. 使用编译器内置断言传递非空信息
在调用memset前添加__builtin_assume(GCC/Clang均支持),直接告知编译器chip指针非空:
void OPN2_Reset(ym3438_t *chip, Bit32u rate, Bit32u clock) { Bit32u i, rateratio; rateratio = (Bit32u)chip->rateratio; __builtin_assume(chip != NULL); // 明确告知编译器指针非空 memset(chip, 0, sizeof(ym3438_t)); ... }
2. 给函数添加非空属性
修改函数声明,通过__attribute__((nonnull))标记第一个参数为非空,让编译器在编译阶段就认定chip不会为空:
// 函数声明处添加非空属性 void OPN2_Reset(ym3438_t *chip, Bit32u rate, Bit32u clock) __attribute__((nonnull(1))); // 函数实现 void OPN2_Reset(ym3438_t *chip, Bit32u rate, Bit32u clock) { Bit32u i, rateratio; rateratio = (Bit32u)chip->rateratio; memset(chip, 0, sizeof(ym3438_t)); ... }
3. 优化memset参数(提升代码健壮性)
将sizeof(ym3438_t)替换为sizeof(*chip),虽不直接解决警告,但能避免后续结构体类型变更时出现尺寸不匹配问题:
memset(chip, 0, sizeof(*chip));
内容的提问来源于stack exchange,提问作者Jonathan Gilbert
相关产品推荐
相关产品推荐

