警告:'memset' 将始终溢出 [-Wfortify-source]

问题描述 投票:0回答:2

试图在

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);

没有显示警告。我做错了什么?

更新。修正了 printf()

c memset
2个回答
1
投票

Attie 已经给出了完整的答案,但这提供了存储套接字地址的替代方法:

struct sockaddr_storage

socket(7) 的手册页说明如下:

套接字 API 提供数据类型 struct sockaddr_storage。
这种类型适合容纳所有
支持特定域的套接字地址结构;它很大
足够并且正确对齐。

sockaddr_storage 结构在程序中很有用
以通用方式处理套接字地址(例如,程序必须 处理 IPv4 和 IPv6 套接字地址)。

所以不是这个:

struct sockaddr a;

你应该使用这个:

struct sockaddr_storage a;

为大多数不同的地址类型获得足够的空间。


1
投票

不幸的是,这些结构不是那样工作的......你会发现

struct sockaddr
是一个“base”定义,它实际上只包括套接字系列字段和一些最小空间预留 - 然后通过类型转换,您可以访问另一个结构的字段。当您使用 IPv6 时,这意味着您将拥有 much 更长的地址,并且需要相应地分配存储空间。

由于各种寻址方案使用不同的信息(例如:地址长度),您需要确保为您尝试使用的内容分配足够的存储空间。

在您的情况下,以下方法可行:

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

/* don't be afraid to clear the whole structure before filling it in too! */
memset(&a, 0, sizeof(a));

当您随后使用它来连接/绑定时,您将在那里进行类型转换。将结构传递给内核时,你几乎可以认为它是传递一个无类型指针......内核知道你正在使用IPv6(因为你在调用

socket()
时这么说了,并且在地址族字段中) ,因此要使用哪种类型。这里的类型转换只是让编译器开心——你仍然在共享完整的 IPv6 信息,以及该结构的大小。

int fd, ret;

fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
ret = connect(fd, (struct sockaddr *)&a, sizeof(a));

将结构视为可以覆盖内存的模板——它只是指示如何读取内存中保存的数据……通过将内存区域转换为另一种类型不会导致底层的“thing “完全改变形状。


如果你在堆上分配地址(不是堆栈),那么当你调用

*alloc()
时,你需要为你正在使用的寻址提供正确的大小。

struct sockaddr_in6 *a;

a = malloc(sizeof *a);
a = malloc(sizeof (struct sockaddr_in6)); /* this works too... */

a = malloc(sizeof (struct sockaddr)); /* this is BROKEN */
© www.soinside.com 2019 - 2024. All rights reserved.