std::map<int,struct> 中的结构体内存泄漏?

Structs in std::map<int,struct> memory leaking?

提问人:Cristian Tamblay 提问时间:10/9/2021 更新时间:10/10/2021 访问量:261

问:

我有以下结构和映射

struct dataStruct{
  unsigned long time;
  int32_t ch0;
  int32_t ch1;
  uint8_t state;
  int16_t temp;
  uint16_t vbat;
  int8_t rssi;
  };

std::map<uint32_t,struct dataStruct> uuidData = {};

还有一个循环,它等待新数据并用它填充地图。(1)

for(;;)
{
    if (data_debug.is_new_data_available())
    {
        uint32_t uuid = data_debug.get_ID();
        uuidData[uuid] = {
            millis(), 
            data_debug.get_data1(), 
            data_debug.get_data2(), 
            data_debug.get_state(), 
            data_debug.get_temperature(),
            data_debug.get_battery_level(),
            data_debug.get_RSSI()
        };
    }
}

这有效,但是当我使用现有 UUID 获取数据时,我的直觉是旧结构永远不会被删除,最终会泄漏。

我在下面有一个替代代码 (2) 试图绕过它,但是当 UUID 被复制时,结构被垃圾填满了。 (1) 中的代码是泄漏还是 c++ 在不再需要结构时自动释放空间?(我知道这听起来像是垃圾回收,但我不知道 c++ 如何处理结构)

(2)

    if(uuidData.count(uuid)){
        uuidData[uuid].time = millis();
        uuidData[uuid].ch0 = data_debug.get_data1();
        uuidData[uuid].ch1 = data_debug.get_data2();
        uuidData[uuid].state = data_debug.get_state();
        uuidData[uuid].temp = data_debug.get_temperature();
        uuidData[uuid].vbat = data_debug.get_battery_level();
        uuidData[uuid].time = data_debug.get_RSSI();
    }
    else{
        uuidData[uuid] = {
            millis(), 
            data_debug.get_data1(), 
            data_debug.get_data2(), 
            data_debug.get_state(), 
            data_debug.get_temperature(),
            data_debug.get_battery_level(),
            data_debug.get_RSSI()
            };
}
C++ ESP32 标准地图

评论

3赞 user4581301 10/9/2021
如果存在,则重用。 将 创建的临时文件复制到 .当对象被移除或映射超出范围时,将处理对象的正确销毁和解除分配。uuiduuidData[uuid] = { ... };{ ... }mapmapuuid
2赞 Nathan Pierson 10/9/2021
为什么你的直觉是旧的结构永远不会被删除?
0赞 Cristian Tamblay 10/9/2021
@NathanPierson 因为我从来不明确叫删除。
3赞 user4581301 10/9/2021
只有你.如果你的代码没有 ,它不需要 .deletenewnewdelete
1赞 Chris 10/9/2021
小说明:由于您使用的是 C++ 而不是 C,因此没有必要编写 .您可以将其简化为 .std::map<uint32_t,struct dataStruct>std::map<uint32_t, dataStruct>

答:

2赞 user4581301 10/9/2021 #1

让我们分解一下示例 1 会发生什么(执行此任务的正确方法)

uuidData[uuid] = {
            millis(), 
            data_debug.get_data1(), 
            data_debug.get_data2(), 
            data_debug.get_state(), 
            data_debug.get_temperature(),
            data_debug.get_battery_level(),
            data_debug.get_RSSI()
        };

        {
            millis(), 
            data_debug.get_data1(), 
            data_debug.get_data2(), 
            data_debug.get_state(), 
            data_debug.get_temperature(),
            data_debug.get_battery_level(),
            data_debug.get_RSSI()
        };

创建并初始化一个临时变量,这是一个自动变量,只有在不再需要它之前才会存在。当表达式结束时,临时将超出范围并被销毁。dataStruct

uuidData[uuid]

查找匹配的密钥。如果找不到,则创建一个空键并将其映射到键。此新功能由 管理。它从哪里来,到哪里去不是你关心的。一旦映射到存在,就会返回对它的引用。uuidDatauuiddataStructdataStructuuidDatadataStructuuid

现在,我们参考了地图中的现有和临时的.只需将右侧临时的内容复制到左侧引用所表示的对象中即可。左侧对象中的任何内容都会被覆盖,但该对象仍然存在,并且仍由 管理。当它从范围中删除或超出范围时,它将被正确销毁和解除分配。当表达式完成时,临时变量会自动销毁(因此名称为自动变量)。dataStructdataStruct=uuidDatauuidDatauuidData

这里没有泄漏的可能性。