提问人:mortelsson 提问时间:9/18/2023 最后编辑:Jan Schultkemortelsson 更新时间:10/2/2023 访问量:227
我可以在 C 中释放()在 C++ 中被 malloc()'ed 的东西吗?
Can I free() something in C that has been malloc()'ed in C++?
问:
我正在为用 C++ 编写的库编写包装器,以便它可以从 C 中使用。在包装器代码中,我制作了大量 c++ 容器底层数据的副本。例如,如果 c++ 库函数返回一个 ,我的包装器将返回一个形式的结构,其中包含来自向量的数据副本。当用户处理完数据时,他们必须释放数据。std::vector<int>
{size_t len; size_t size; void *arr;}
arr
我的问题是:用户(C 代码)调用已在 C++ 中:d的指针是否总是合法的?或者我必须在包装器代码中创建等效函数?free()
malloc()
答:
你可以混合使用 C++ 和 Cstd::malloc
free
std::malloc
在 C++ 中定义,其中据说具有与 C 相同的内容和含义(有一些变化,例如命名空间)。此外,[c.malloc] 说:<cstdlib>
<stdlib.h>
void* aligned_alloc(size_t alignment, size_t size); void* calloc(size_t nmemb, size_t size); void* malloc(size_t size); void* realloc(void* ptr, size_t size);
效果:这些函数具有 C 标准库中指定的语义。
这意味着您可以在 C++ 中分配一些内存,并将其传递给一些调用 .std::malloc
free
注意:混合使用不同的标准库或混合使用同一标准库的不同版本(调试/发布)可能仍然是一个问题,但这适用于所有语言功能。
C++ 标准库不使用std::malloc
话虽如此,用于由您建议的类似的东西分配的内存是不安全的。
默认情况下,所有进行内存分配的容器都使用 .free
std::vector
std::allocator
operator new
混合和将是未定义的行为,即使获取和释放内存的底层操作系统功能是相同的。new
free
如何在 C 语言中使用std::vector
// C23
struct vector {
// note: 3 pointers in size is usually the bare minimum which is needed for
// a std::vector.
alignas(void*) unsigned char data[3 * sizeof(void*)];
};
// Note the symmetric interface; it doesn't matter how init/destroy are
// implemented to the user.
void vector_init(struct vector*);
void vector_destroy(struct vector*);
// Also add this and other functions to make the vector useful.
void vector_push(struct vector*, int element);
int main() {
vector v;
vector_init(&v); // no malloc, no free
vector_push(&v, 42);
vector_destroy(&v);
}
到目前为止,我们基本上只定义了一个包含一定数量的字节和三个不透明的函数。所有代码都与 C23 兼容,我们可以在 C++ 中实现实际功能。struct vector
// C++20
static_assert(alignof(vector::data) >= alignof(std::vector));
static_assert(sizeof(vector::data) >= sizeof(std::vector));
extern "C" void vector_init(vector* v) {
std::construct_at(reinterpret_cast<std::vector<int>*>(v->data));
}
extern "C" void vector_destroy(vector* v) {
std::destroy_at(reinterpret_cast<std::vector<int>*>(v->data));
}
extern "C" void vector_push(vector* v, int element) {
auto* vec = std::launder(reinterpret_cast<std::vector<int>*>(v->data));
vec->push_back(element);
}
C++ 端使用 (或者在 C++20 之前,您可以使用 placement new)。我们在 的原始字节中创建一个 。
请注意,我们没有在此代码中调用 、 、 或任何位置。 仍然负责所有内存管理。std::construct_at
std::vector
vector::data
new
delete
malloc
free
std::vector
评论
std::malloc
free
std::malloc
std::free
malloc
评论
malloc
free
malloc
free