容器renew导致的指针失效

本文通过一个示例展示了在C++中使用vector迭代器时可能遇到的问题,即当向vector添加元素导致其重新分配内存时,之前保存的迭代器将失效。为了解决这个问题,建议避免在非临时场景中使用vector迭代器,或者在使用前预留足够的内存空间以防止vector的renew。在示例中,通过在添加元素前调用reserve方法,成功避免了迭代器失效,从而得到了正确的排序结果。
摘要由CSDN通过智能技术生成

问题场景:

以vector为例,有时候我们会把原始数据列表作为vector数组,同时把需要排序或其他处理的数组使用指向原始vector的迭代器数组

示例代码:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

class Person
{
public:
    Person()
    {
        age = 0;
    }

    string name;
    int age;
};

typedef vector<Person>::iterator PersonPtr;

int main(int argc, char* argv[])
{
    vector<Person> personArray;

    Person p1;
    p1.age = 10;
    p1.name = "小明";

    Person p2;
    p2.age = 30;
    p2.name = "王亮";

    Person p3;
    p3.age = 12;
    p3.name = "小丽";

    Person p4;
    p4.age = 9;
    p4.name = "小华";

    personArray.push_back(p1);
    personArray.push_back(p2);
    personArray.push_back(p3);
    personArray.push_back(p4);

    vector<PersonPtr> personItArray;
    for(auto it = personArray.begin(); it != personArray.end(); ++it)
    {
        personItArray.push_back(it);
    }
    std::stable_sort(personItArray.begin(), personItArray.end(), [](PersonPtr a, PersonPtr b){return a->age < b->age;});
    
    //在后面处理中又插入了一个新的person
    Person p5;
    p5.name = "李雷";
    p5.age = 15;
    personArray.push_back(p5);

    cout << personArray.capacity() << endl;
    for(auto personPtr : personItArray)
    {
        cout << "name:" << personPtr->name << ", age:" << personPtr->age << endl;
    }
    return 0;
}

运行结果, 程序core掉:

问题原因:

4个元素的时候,vector内部处于需要renew的边界,当再插入1个的时候,出发了renew,之前的迭代器数组中插入的迭代器指向了错误的地址

解决方式:

尽量避免使用非临时场景的vector迭代器、指针,如果必须要使用,确保vector不会再次renew而导致指向错误内存

可以根据需要提前reserve一个足够的空间, 中前面问题代码中增加 reserve:

    Person p4;
    p4.age = 9;
    p4.name = "小华";

    personArray.reserve(20); //提前reserve足够空间
    personArray.push_back(p1);

 得到正确结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DHCP是动态主机配置协议(Dynamic Host Configuration Protocol)的缩写,它是一种网络协议,用于向网络中的设备分配IP地址、子网掩码、网关等网络配置信息。 当设备首次连接到网络上时,它会使用DHCP协议来请求并获取一个可用的IP地址、子网掩码等配置信息。此时,DHCP服务器会向设备分配一个IP地址,并发送一个分配报文。设备在接收到IP地址后,会在一段时间内(称为租约时间)保留该IP地址,并使用该IP地址与其他设备进行通信。 租约时间结束后,设备需要续约(Renew)它所使用的IP地址。它会发送一个DHCP renew报文给DHCP服务器,以请求继续使用该IP地址。这个报文通常包含设备的MAC地址和已分配的IP地址等信息,以便服务器能够识别并续约该IP地址。 DHCP服务器在接收到DHCP renew报文后,会检查该IP地址是否仍然可用。如果可用,服务器会更新租约时间,并向设备发送一个确认报文。设备在收到确认报文后,会继续使用该IP地址,其它网络设备也能继续与该设备进行通信。 如果DHCP服务器在一段时间内没有收到设备的DHCP renew报文,或者服务器没有可用的IP地址分配给设备,则设备在租约到期后会丢失IP地址,并重新发起一个DHCP请求,重新获取一个可用的IP地址。 总之,DHCP renew报文是设备为继续使用已分配的IP地址而向DHCP服务器发送的请求报文。这种续约的机制使得网络中的设备能够动态获取和更新IP地址,提高了IP资源的利用率并简化了网络管理。 ### 回答2: DHCP(动态主机配置协议)是一种用于动态分配IP(Internet Protocol)地址的网络协议。当设备连接到网络时,它需要获取一个有效的IP地址以便与其他设备进行通信。 DHCP租约(lease)是指分配给设备的IP地址的有效期。在租约到期之前,设备需要向DHCP服务器发送DHCP Renew请求来更新租约并延长IP地址的使用权限。 DHCP Renew报文是设备发送给DHCP服务器的用于更新租约的请求。当设备触发DHCP Renew操作时,它会在DHCP报文中包含自己的MAC(Media Access Control)地址和当前正在使用的IP地址。DHCP服务器会收到该报文,并根据设备的MAC地址查找相应的租约信息。 如果DHCP服务器发现该设备之前已经分配了一个有效的租约,并且该租约还未到期,它会更新租约的到期时间,并向设备返回DHCP ACK(Acknowledgment)报文,表示租约续约成功。设备会根据DHCP ACK报文中提供的新的到期时间更新自己的租约。 然而,如果设备之前的租约已经达到了到期时间,或者DHCP服务器没有找到该设备的租约信息,它会向设备返回DHCP NAK(Negative Acknowledgment)报文,表示无法续约。在这种情况下,设备需要重新发起DHCP Discover请求,以获取一个新的可用IP地址。 总结起来,DHCP Renew报文是设备发送给DHCP服务器的用于更新租约的请求。它包含设备的MAC地址和当前正在使用的IP地址。通过DHCP Renew操作,设备可以续约并延长IP地址的使用权限。 ### 回答3: DHCP Renew报文是Dynamic Host Configuration Protocol(动态主机配置协议)中的一种特定类型的报文。当客户端使用DHCP协议进行网络连接时,它会自动向DHCP服务器发送DHCP Discover报文,以请求分配一个可用的IP地址和其他网络配置信息。 DHCP Renew报文是在客户端已经从DHCP服务器获得IP地址之后发送的。它用于向DHCP服务器确认之前分配的IP地址是否仍然有效,并延续租约的时间。租约是DHCP服务器为客户端分配IP地址和其他网络配置信息的一段时间。 DHCP Renew报文通常包含客户端的IP地址和其他标识信息,以及用于更新租约的请求信息。当DHCP服务器收到DHCP Renew报文时,它会检查客户端提供的标识信息和IP地址,来确认该IP地址是否仍然在DHCP服务器的租约列表中,并且租约是否可以更新。 如果DHCP服务器确认客户端提供的IP地址仍然有效,它会回复一个DHCP Acknowledge(确认)报文,其中包含更新后的租约时间。如果DHCP服务器无法更新租约,可能是因为IP地址已被其他设备使用或租约已过期,它会发送一个DHCP Nak(拒绝)报文给客户端,并要求客户端重新发送DHCP Discover报文,以获取新的IP地址和网络配置信息。 综上所述,DHCP Renew报文是DHCP客户端向DHCP服务器发送的请求,用于确认之前获得的IP地址是否仍有效,并延续租约的时间。它的目的是使DHCP客户端能够维持已经分配的IP地址的使用权,以保持网络连接的稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值