You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C接口内存泄漏问题排查与修复(C++实现)

C/C++跨语言API内存泄漏修复与优化方案

基于纯C实现供C语言调用的API,接口定义在.h文件中,实现逻辑用C编写,当前场景下适配良好。现有代码存在两处问题:销毁函数拼写错误,以及堆内存未正确释放导致的泄漏。

已确认的问题点

  • 销毁函数拼写错误:实现中的destory应为头文件定义的destroy
  • 内存泄漏:create函数中通过new Person[size]分配的Person数组,在销毁时未被释放,仅释放了PersonArray结构体本身

内存泄漏修复方案

修正后的销毁函数需要先释放内部的Person数组,再释放PersonArray结构体,同时增加空指针检查避免非法访问:

void destroy(PersonArray *array) {
  if (array == nullptr) {
    return;
  }
  // 先释放数组内存
  delete[] array->person;
  // 再释放结构体本身
  delete array;
}

完整修正后的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 destroy(PersonArray *array) {
  if (array == nullptr) {
    return;
  }
  delete[] array->person;
  delete array;
}

int fillArray(PersonArray *array) {
  if (array == nullptr) {
    return 1;
  }
  auto data = /* 通过RPC获取std::vector<otherNamespace::Person> */;
  // 增加边界检查:避免RPC返回的数据量小于array->size导致越界
  if (data.size() < array->size) {
    return 2; // 返回错误码表示数据不足
  }
  for (size_t i = 0; i < array->size; i++) {
    array->person[i] = convert(data.at(i));
  }
  
  return 0;
}

更适配场景的优化思路

1. 使用不透明句柄隐藏内部实现

将PersonArray改为不透明结构体,头文件中只声明结构体类型,不暴露内部成员,这样可以避免调用者直接修改内部指针,同时方便后续修改实现而不影响C端调用:

头文件修改:

extern "C" {
  typedef struct Person Person;
  typedef struct PersonArray PersonArray;

  PersonArray *create(size_t size);
  void destroy(PersonArray *array);
  int fillArray(PersonArray *array);
  // 新增获取Person的接口,供C调用者访问数据
  const Person* getPerson(const PersonArray* array, size_t index);
}

C++实现中补充结构体定义和接口:

struct Person {
  const char *name;
  uint32_t age;
  uint32_t post_code;
};

struct PersonArray {
  std::vector<Person> persons; // 用C++ vector管理内存,自动处理释放
};

const Person* getPerson(const PersonArray* array, size_t index) {
  if (!array || index >= array->persons.size()) {
    return nullptr;
  }
  return &array->persons[index];
}

这种方式利用C++容器自动管理内存,无需手动调用delete[],减少内存泄漏风险。

2. 字符串内存管理优化

当前convert函数直接赋值name指针,如果RPC返回的o_person.name是临时内存(比如栈上字符串或RPC内部管理的内存),会导致C调用者使用时出现悬空指针。可以改为复制字符串:

#include <cstring>

static inline Person convert(const otherNamespace::Person &o_person) {
  Person p{};
  // 复制字符串到堆内存,确保生命周期由API管理
  if (o_person.name) {
    p.name = strdup(o_person.name);
  }
  p.age = o_person.age;
  p.post_code = o_person.post_code;
  return p;
}

同时需要在销毁时释放字符串内存:

void destroy(PersonArray *array) {
  if (!array) return;
  for (size_t i = 0; i < array->size; i++) {
    free(const_cast<char*>(array->person[i].name)); // strdup分配的内存用free释放
  }
  delete[] array->person;
  delete array;
}

内容的提问来源于stack exchange,提问作者Xershy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 16:10:53