我可以在 C 中 free() 一些已经在 C++ 中 malloc() 过的东西吗?

问题描述 投票:0回答:1

我正在为用 C++ 编写的库编写一个包装器,以便可以从 C 中使用它。在包装器代码中,我制作了 C++ 容器底层数据的大量副本。例如。如果 C++ 库函数返回

std::vector<int>
,我的包装器将返回
{size_t len; size_t size; void *arr;}
形式的结构,其中
arr
包含向量中数据的副本。当用户使用完数据后,他们必须释放它。

我的问题是:用户(C 代码)在 C++ 中已 free():d 的指针上调用

malloc()
是否
总是
合法?或者我必须在我的包装器代码中创建一个等效的函数吗?

c++ c malloc free
1个回答
0
投票

您可以混合使用 C++ 的
std::malloc
和 C 的
free

C++中的

std::malloc
<cstdlib>
中定义,据说它与C中的
<stdlib.h>
具有相同的内容和含义(有一些变化,例如命名空间)。 这意味着您可以在 C++ 中使用
std::malloc
分配一些内存,并将其传递给某个调用
free
的 C 函数。

C++ 标准库不使用
std::malloc

话虽如此,使用

free
来分配像您建议的
std::vector
这样的内存是不安全的。 所有进行内存分配的容器默认使用
std::allocator
,它使用
operator new

混合

new
free
将是未定义的行为,即使获取和释放内存的底层操作系统函数是相同的。

如何在C中使用
std::vector

// C23
struct vector {
    alignas(void*) unsigned char data[3 * sizeof(void*)];
};

void vector_init(struct vector*);
void vector_push(struct vector*, int element);
void vector_destroy(struct vector*);

int main() {
    vector v;
    vector_init(&v);
    vector_push(&v, 42);
    vector_destroy(&v);
}

到目前为止,我们基本上只是定义了一个

struct vector
来包含一定数量的字节和三个不透明函数。所有代码都是C23兼容的,我们可以用C++实现实际功能。

// C++20
static_assert(alignof(vector::data) >= alignof(std::vector));
static_assert(sizeof(vector::data) >= sizeof(std::vector));

extern "C" {

void vector_init(struct vector* v) {
    std::construct_at(reinterpret_cast<std::vector<int>*>(v->data));
}
void vector_destroy(struct vector* v) {
    std::destroy_at(reinterpret_cast<std::vector<int>*>(v->data));
}
void vector_push(struct vector* v, int element) {
    auto* vec = std::launder(reinterpret_cast<std::vector<int>*>(v->data));
    vec->push_back(element);
}

}

C++ 端使用

std::construct_at
(或者在 C++20 之前,您可以使用新的放置)。我们在
std::vector
的原始字节中创建一个
vector::data
。 请注意,我们在此代码中的任何位置都没有调用
new
delete
malloc
free
std::vector
仍然负责所有内存管理。

© www.soinside.com 2019 - 2024. All rights reserved.