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

IPv6地址struct sin6_addr操作中memset溢出警告疑问

问题描述

操作struct sin6_addr中的IPv6地址(例如清空地址)时,编写了如下代码:

struct sockaddr a;
memset(&(((struct sockaddr_in6 *)&a)->sin6_addr.s6_addr), 0, 16);
printf("SIZEOF: %lu\n", sizeof((((struct sockaddr_in6 *)&a)->sin6_addr.s6_addr)));

编译时出现如下警告:

1.c:34:2: warning: 'memset' will always overflow; destination buffer has size 8, but size argument is 16 [-Wfortify-source]
        memset(&(((struct sockaddr_in6 *)&a)->sin6_addr.s6_addr), 0, 16);

但printf输出的sizeof结果为16字节,看起来缓冲区应该足够。改用以下写法时则无警告:

struct sockaddr a;
struct in6_addr aa;
aa = ((struct sockaddr_in6 *)&a)->sin6_addr.s6_addr;
memset(&aa, 0, 16);

请问哪里操作错误?

问题原因与解决方法

核心问题是**struct sockaddr的内存空间不足以容纳struct sockaddr_in6的完整结构**。

  • struct sockaddr是通用套接字地址结构体,通常大小仅为16字节(不同系统可能略有差异,但肯定小于struct sockaddr_in6)。而struct sockaddr_in6包含sin6_family、sin6_port、sin6_flowinfo、sin6_addr等多个字段,仅sin6_addr.s6_addr就占16字节,整个struct sockaddr_in6的大小远大于struct sockaddr。
  • 你将struct sockaddr a强制转换为struct sockaddr_in6*后,访问sin6_addr.s6_addr时,该地址已经超出了a的内存范围。编译器的-Wfortify-source检测到了这个内存越界风险,因此抛出缓冲区溢出警告。
  • 第二种写法中,你把sin6_addr.s6_addr的值拷贝到了独立的struct in6_addr aa变量中,aa拥有完整的16字节内存空间,memset操作不会越界,所以没有警告。

正确的做法是直接使用struct sockaddr_in6类型的变量来操作IPv6地址:

struct sockaddr_in6 a;
// 用sizeof代替硬编码的16,提升代码可移植性
memset(&a.sin6_addr.s6_addr, 0, sizeof(a.sin6_addr.s6_addr));

内容的提问来源于stack exchange,提问作者Mikhail Zakharov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 06:23:12