C++:在被本地字符串捕获后释放或销毁 malloc 的 char *?

C++: free or destroy malloc'd char * after it is captured by a local string?

假设我执行以下操作:

char *get_data(...) {
    char *c_style = (char *) malloc(length * sizeof(char));
    load_c_string_with_my_c_function(c_style, length, input);
    return c_style;
}

int main() {
   std::string data(get_data(...));
   // free(data.c_str()); ?? -- are the malloc'd bytes now managed?
   return 0;
}

有什么方法可以释放get_data()分配的内存吗?评论 free(data.c_str()); 有用吗?

您不能拨打电话 free(data.c_str()); 或类似的电话。 std::string 管理自己的内存,即使 c_str() 获得的指针也会在 std::string 超出范围后自动失效。

但是,您确实需要释放从函数调用返回的 c_stylestd::string 可以处理它自己的内存,但它只是 malloc 的内存的一个副本,不受管理。

这样做:

int main() {
    char *result = (get_data(...)
    std::string data(result);
    // free(data.c_str()); ?? -- are the malloc'd bytes now managed?
    free(result);
    return 0;
}

一旦你这样做了

std::string data(get_data(...));

无法取回 get_data() return 编辑的指针,因此您会泄漏该内存。要解决此问题,首先需要 get_data() return 一个 std::string,这样您根本不必担心内存管理。那会给你

std::string get_data(...) {
    std::string data(length, '[=11=]');
    load_c_string_with_my_c_function(data.data(), length, input); // requires C++17
    // load_c_string_with_my_c_function(&data[0], length, input); // use this for pre-C++17 compilers
    return data;
}

现在没有内存泄漏。如果你不能这样做那么你需要捕获指针,用它来初始化字符串,然后像

一样释放指针
char* ret = get_data(...);
std::string data(ret);
free(ret);

您不能删除指针,因为您没有保留对它的引用。你需要做的:

int main() {
   char* cstr = get_data(...);
   std::string data(cstr);
   free(cstr);
   return 0;
}

或者直接将数据写入字符串更好:

std::string get_data(...) {
    std::string data(length, '[=11=]');
    load_c_string_with_my_c_function(&data[0], data.size(), input);
    return data;
}

您可能需要将 std::string and/or 传递 data.size()-1load_c_string_with_my_c_function 的长度加 1,具体取决于 length 参数的规范load_c_string_with_my_c_function 个。

Is there any way to release the memory that get_data() allocated?

不,您丢失了指向它的指针。

Would the commented free(data.c_str()); Work?

没有。 std::string 将您的数据复制到它拥有和管理的新字符串中。您不能合法地取消分配 std::string 自己分配的内存,这也不能解决必须取消分配原始分配内存的问题。

要么始终使用 std::string(首选!),要么首先捕获 main 内的指针:

int main()
{
   auto cstr = get_data(...);
   std::string data(cstr);
   free(cstr);
}

问题是,这不是异常安全的,这就是为什么我们首先拥有像 std::string 这样的好东西。它可以用一些自由 trycatch 来解决,但它会很难看。

此外,由于您已经拥有 get_data,大概是出于某种原因,您可能会考虑 string_view 超过您已经分配的实际内存,除非您确实需要 data成为拥有的副本。

int main()
{
   auto cstr = get_data(...);
   std::string_view data(cstr);  // no copy! just features
   free(cstr);
}

(其他地方的评论表明这可能是您真正想要的。)

现在尝试拥有 get_data return 具有明确所有权和生命周期语义的东西(std::unique_ptrstd::vectorstd::string?.. 哈哈)和你是金色的。