You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何告知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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 14:22:47