【问题标题】:getaddrinfo addrinfo result in stack or heapgetaddrinfo addrinfo 导致堆栈或堆
【发布时间】:2011-07-22 09:06:54
【问题描述】:

至少我有点困惑。 getaddrinfo() 调用“更新”指向 addrinfo 结构的指针,当我要在同一范围(该函数)中使用 addrinfo 时,一切都很好,但是如果我将结构复制到另一个结构(通过分配它)会发生什么。

请帮助我了解正在发生的基础知识(而不是寻求替代方法的建议)。

如果我错了,请纠正我: a) getaddrinfo() 需要一个指向 addrinfo 的 struct-pointer 的指针。 b) getaddrinfo 在当前函数范围内创建一个 addrinfo 结构并更新 a) 中所需的指针

现在我真正的问题是:我想将该 addrinfo 存储在其他地方。使用赋值给其他指针不会做深拷贝,函数执行后所有指针都失效了?

最好举一个极其简化的例子:

void GetAddrInfo(struct addrinfo *update)
{
    struct addrinfo *res;
    getaddrinfo(xx,xx,xx,&res);

    //is this save? After this 'scope' ends all pointed fields are invalid?
    //this doesn't copy the linked list ai_next.
    *update=*res; 
}

在 getaddrinfo 上直接使用 &update 似乎不起作用,因为问题仍然存在:原始结构在函数范围结束后被销毁。

任何人都可以在这里给我更多的见解(请解释什么在哪里创建和在哪里销毁,堆栈,堆所有信息都是受欢迎的)

【问题讨论】:

    标签: c networking struct heap-memory stack-memory


    【解决方案1】:

    函数作用域结束后原始结构被销毁

    不,结构的指针被破坏了。其余数据仍在堆中。如果您在完成结果后不调用freeaddrinfo(),这将是内存泄漏。

    我想将该 addrinfo 存储在其他地方

    由于数据仍然存在,请随意复制指针;不需要深拷贝。从你的例子:

    void GetAddrInfo(struct addrinfo **update)  /* pointer to pointer */
    {
        struct addrinfo *res;
        getaddrinfo(xx,xx,xx,&res);
        *update=res;  /* save the pointer to the struct */
    }
    

    你可以简单地调用这个函数:

    struct addrinfo *mycopy;
    GetAddrInfo(&mycopy);
    

    【讨论】:

    • 感谢您的反馈。如果我错了,请纠正我:通常当我创建一个结构实例时,它将在堆栈上正确创建并在当前范围完成后“清除”?那么 getaddrinfo 是这里的特例吗?有没有办法让我找到保存数据的函数?
    • @Ger 所有局部变量都在堆栈上,正确。但是您没有创建 addrinfo 结构; getaddrinfo() 正在使用malloc() 为您创建结构,这就是它在堆中的原因。您所创建的只是指向该结构的 指针。当函数结束时,您的 指针 消失,但结构本身仍在堆中。
    • 这些可能是基本问题;但是所有其他更新结构指针的 c 函数都以相同的方式工作吗?
    • @Ger getaddrinfo() 有点独特,因为它接受一个指向指针的指针并为用户生成一个链表。在我的脑海中,我想不出任何其他功能可以做到这一点。大多数 C 函数采用简单的结构指针(不是指向指针的指针);这些函数通常期望用户预先分配结构,而用户通常只是在堆栈上执行此操作。如有疑问,请在互联网上查找示例。
    • @Ger:不,您需要检查每个函数的文档
    【解决方案2】:

    getaddrinfo 分配addrinfo 结构的列表,并为您提供指向列表头部的指针。完成后,通过将此指针传递给 freeaddrinfo 来释放所有分配的内存。

    您正在做的事情足够安全,但会泄漏内存。

    void GetAddrInfo(struct addrinfo **update)
    {
        getaddrinfo(xx,xx,xx,update);
    }
    
    
    addrinfo * myai;
    GetAddrInfo(&myai);
    freeaddrinfo(myai)
    

    这种方法不会泄漏内存 - 您只是检索指向 addrinfo 列表头的指针。

    【讨论】:

    • 我知道 freeaddrinfo(),希望保持讨论清晰。所以你说函数范围结束后结构不会“无效”?所以实际上在我调用 freeaddrinfo 之前它不会被删除?
    • @Ger Teunis:没错。它是从一些私有分配机制中分配的,并且在您调用 freeaddrinfo 之前完全安全
    • @Ger Teunis:虽然,您不能将update 传递给freeaddrinfo - 它是res 字段的副本,它并不指向原始列表头。我会更新答案。
    • 谢谢,所以 getaddrinfo 是一种特殊情况,它不会在范围退出时清除 addrinfo 结构?
    猜你喜欢
    • 2015-05-21
    • 2012-06-03
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 2011-07-02
    相关资源
    最近更新 更多