【问题标题】:Safely converting from struct sockaddr to struct sockaddr_storage安全地从 struct sockaddr 转换为 struct sockaddr_storage
【发布时间】:2016-10-07 14:56:51
【问题描述】:

我有一个函数,它接受“struct sockaddr *”作为参数(我们称之为 input_address),然后我需要对该地址进行操作,它可能是 sockaddr_in 或 sockaddr_in6,因为我同时支持 IPv4 和 IPv6 .

我遇到了一些内存损坏并试图追查它的源头,在此过程中发现了一些可疑的代码,所以我想验证这是否是正确的做事方式。

struct sockaddr_storage *input_address_storage = (struct sockaddr_storage *) input_address;
struct sockaddr_storage result = [UtilityClass performSomeOperation: *input_address_storage];

起初我认为第一行中的强制转换是安全的,但在第二行中我需要取消引用该指针,这似乎是错误的。我担心的原因是它最终可能会复制超出原始结构所在位置的内存(因为 sockaddr_in 比 sockaddr_in6 短)。我不确定这是否会导致内存损坏(我的猜测是不会),但是这段代码给我的感觉很糟糕。

我无法改变我的函数采用“struct sockaddr *”这一事实,所以似乎很难解决这种类型的代码,但我想避免从我应该的内存位置复制不是。

如果有人能验证我的做法是否错误,以及解决此问题的最佳方法,我将不胜感激。

编辑:管理员出于某种原因将我的 C 标记更改为 C#。我给出的代码主要是 C,其中一个函数调用来自目标 C,这并不重要。那个调用可能是 C。

【问题讨论】:

    标签: c pointers tcp network-programming ipv6


    【解决方案1】:

    您的方法的问题是您将现有的struct sockaddr* 转换为struct sockaddr_storage*。想象一下,如果原始文件是“struct sockaddr_in. Sincesizeof(struct sockaddr_in)

    struct sockaddr_storage 本质上是一个container,包含您的struct sockaddr_instruct sockaddr_in6

    因此,当您想传入struct sockaddr* 对象但又想为sockaddr_insockaddr_in6 分配足够的内存时,它很有用。

    一个很好的例子是recvfrom(3) 调用:

    ssize_t recvfrom(int socket, void *restrict buffer, size_t length,
                     int flags, struct sockaddr *restrict address,
                     socklen_t *restrict address_len);
    

    由于address需要struct sockaddr*对象,我们先构造一个struct sockaddr_storage,并传入:

    struct sockaddr_storage address;
    socklen_t address_length = sizeof(struct sockaddr_storage);
    ssize_t ret = recvfrom(fd, buffer, buffer_length, 0, (struct sockaddr*)&address, &address_length);
    
    if (address.ss_family == AF_INET) {
      DoIpv4Work((struct sockaddr_in*)&address, ...);
    } else if (address.ss_family == AF_INET6) {
      DoIpv6Work((struct sockaddr_in6*)&address, ...);
    }
    

    你的方法和我的不同之处在于我分配了一个struct sockaddr_storage,然后将其用作struct sockaddr,但你执行REVERSE,然后使用struct sockaddr,然后使用它作为struct sockaddr_storage

    【讨论】:

    • 感谢您的解释。你说的有道理,但它并不能直接解决我的问题,因为我的要求是我有一个接受“struct sockaddr *”的函数,所以我必须做相反的事情。所以问题是,假设我需要做相反的事情,那么正确的方法是什么。
    猜你喜欢
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 2014-06-17
    • 2015-06-21
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    • 2013-09-23
    相关资源
    最近更新 更多