【问题标题】:C API: Error allocating / deallocating memory for arrayC API:为数组分配/释放内存时出错
【发布时间】:2022-10-13 16:57:31
【问题描述】:

我正在为 C 实现一个 API。代码库本身纯粹是用 C++ 编写的,我只打算为使用 C 的任何消费者提供所述接口。接口定义在。H文件,而实现本身是用 C++ 编写的。我多次阅读过,使用 C++ 实现 C 接口并不是最好的主意,但在我的情况下效果很好。

无论如何,标头定义看起来类似于:

extern 'C' {
  typedef struct Person {
    const char *name;
    uint32_t age;
    uint32_t post_code;
  } Person;

  typedef struct PersonArray {
    Person *person;
    size_t size;
  } PersonArray;

  PersonArray *create(size_t size);
  void destroy(PersonArray *array);
  int fillArray(PersonArray *array);
  
}

我希望消费者检索 PersonArray 的句柄,其中包含一个 Person 结构数组,分配的大小传递给create() function

由于实现是在 C++ 中,我尝试通过以下方式分配内存:

static inline Person convert(const otherNamespace::Person &o_person) {
  Person p{};
  p.name = o_person.name;
  p.age = o_person.age;
  p.post_code = o_person.post_code;
  return p;
}

PersonArray *create(size_t size) {
  if (size <= 0) {
    return nullptr;
  }

  PersonArray *array = new PersonArray();
  array->size = size;

  array->person = new Person[size]
  return array;
}

void destory(PersonArray *array) {
  delete array;
}

int fillArray(PersonArray *array) {
  if (array == nullptr) {
    return 1;
  }
  auto data = // retrieve std::vector<otherNamespace::Person> via RPC
  for (auto i{0U}; i < array->size; i++) {
    array->person[i] = convert(data.at(i);
  }
  
  return 0;
}

不幸的是,这种方法似乎不能正常工作,因为当使用像 valgrind 这样的 memchecker 时,堆上仍然有未正确释放的块。我想new Person[size] 行没有被释放。

知道如何解决此内存泄漏吗?或者是否有另一种更适合这个特定用例的设计?如果可能的话,我真的很想用 C++ 来实现。

【问题讨论】:

  • 我数了两个new 和一个delete。那么为什么没有delete array-&gt;person
  • 有没有办法同时删除PersonArray 并释放结构的成员?我真的必须先delete array-&gt;person 然后再拨打delete array 吗? @KamilCuk
  • 此外,代码*array-&gt;person[i] = // fill with data 看起来很奇怪。你在做浅拷贝吗?请提供minimal reproducible example
  • Isn't there a way to delete PersonArray and deallocate the members of the struct at the same time? 不,每个程序都有一个堆,一切都是按顺序发生的。 Do I really have to first delete array-&gt;person and then call delete array afterwards? 是的。 (为什么会让人困惑?你“真的”做了两个new,所以现在你真的必须做两个delete
  • @GM在我的初始帖子中添加了一个编辑,显示了如何复制数据。不确定这是否是最好的方法,总是愿意接受更好的建议。还在学习 :)

标签: c++ c memory-management c-api


【解决方案1】:

您必须在数组之前对 person 使用 delete,但由于它是使用 new [] 分配的,因此您必须使用 delete [] 删除它。

void destory(PersonArray *array) {
  if (array) {
      if (array->person) {
          delete [] array->person;
      }
      delete array;
  }
}

【讨论】:

  • 这确实解决了valgrind的问题,只是出于好奇,是否有一种“更好”的方式来分配内存而不必使用双重释放?也许我使用第二个结构来保持数组句柄的设计是错误的?
猜你喜欢
  • 2018-10-05
  • 1970-01-01
  • 2011-05-16
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-28
  • 1970-01-01
  • 2018-01-29
相关资源
最近更新 更多