msgpack / msgpack-c

MessagePack implementation for C and C++ / msgpack.org[C/C++]
Other
3.03k stars 883 forks source link

memory leak #868

Closed miaovictor closed 10 months ago

miaovictor commented 4 years ago

i wrap messagepack like this, bug it have memory Leak, could you help me check this code?

message_pack.h

#include <string>
#include <msgpack.hpp>

// https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor

namespace mpack {
class Object {
 public:
  Object();

  template<typename T>
  void Set(const std::string &key, const T &value) {
    maps_.insert(std::make_pair(key, value));
  }

  void Set(const std::string &key, const std::string &value);

  template<typename T>
  void Set(const std::string &key, const std::vector<T> &value) {
    msgpack::object obj(value, zone_);
    maps_.insert(std::make_pair(key, obj));
  }

  void SetObject(const std::string &key, const Object &value);

  template<typename T>
  T Get(const std::string &key, T defaultValue) {
    auto iter = maps_.find(key);
    if (iter == maps_.end()) {
      return defaultValue;
    } else {
      T t;
      iter->second.convert(t);
      return t;
    }
  }

  Object GetObject(const std::string &key);

  std::string Encode();
  bool Decode(const std::string &data);
  bool Decode(const std::vector<char> &data);

 private:
  std::map<std::string, msgpack::object> maps_;
  msgpack::zone zone_;
};
}

message_pack.cpp

#include "message_pack.h"

namespace mpack{

Object::Object() {
}

void Object::Set(const std::string &key, const std::string &value) {
  msgpack::object obj(value, zone_);
  maps_.insert(std::make_pair(key, obj));
}

void Object::SetObject(const std::string &key, const Object &value) {
  msgpack::object obj(value.maps_, zone_);
  maps_.insert(std::make_pair(key, obj));
}

Object Object::GetObject(const std::string &key) {
  auto iter = maps_.find(key);
  if (iter == maps_.end()) {
    return Object();
  } else {
    Object obj;
    iter->second.convert(obj.maps_);
    return obj;
  }
}

std::string Object::Encode() {
  msgpack::sbuffer buff;
  msgpack::packer<msgpack::sbuffer> packer(&buff);
  packer.pack(maps_);
  std::string result(buff.data(), buff.size());
  buff.release();
  return result;
}

bool Object::Decode(const std::string &data) {
  msgpack::object_handle oh = msgpack::unpack(data.data(), data.size());
  msgpack::object obj = oh.get();

  if (obj.type == msgpack::type::MAP) {
    msgpack::object_kv *kvs = obj.via.map.ptr;
    msgpack::object_kv *kvs_end = obj.via.map.ptr + obj.via.map.size;

    for (; kvs < kvs_end; kvs++) {
      if (kvs->key.type != msgpack::type::STR) {
        return false;
      }
      std::string key;
      kvs->key.convert(key);
      msgpack::object value = kvs->val;
      maps_.insert(std::make_pair(key, value));
    }

    return true;
  }

  return false;
}

bool Object::Decode(const std::vector<char> &data) {
  msgpack::object_handle oh = msgpack::unpack(data.data(), data.size());
  msgpack::object obj = oh.get();

  if (obj.type == msgpack::type::MAP) {
    msgpack::object_kv *kvs = obj.via.map.ptr;
    msgpack::object_kv *kvs_end = obj.via.map.ptr + obj.via.map.size;

    for (; kvs < kvs_end; kvs++) {
      if (kvs->key.type != msgpack::type::STR) {
        return false;
      }
      std::string key;
      kvs->key.convert(key);
      msgpack::object value = kvs->val;
      maps_.insert(std::make_pair(key, value));
    }

    return true;
  }

  return false;
}

}
towen commented 2 years ago

I am running into a similar issue. Msgpack-c seems to leak memory on stm32. @miaovictor did you ever find a solution?

OopsLouie commented 11 months ago

I also find msgpack memory leak on Jetson TX2, 300MB msgpack data consumes 1.8G heap after unpack. @towen Did you find a solution?

OopsLouie commented 11 months ago

I just found the key to the problem, msgpack did free the memory while malloc didn't. just call malloc_trim after unpack :>)

redboltz commented 10 months ago

@OopsLouie , It seems that your solution is right. It is out of msgpack-c issue but maybe glibc implementation issue or just usage. So I close the issue. Thank you for the comments!