mor*_*son 4 c c++ malloc free language-lawyer
我正在为用 C++ 编写的库编写一个包装器,以便可以从 C 中使用它。在包装器代码中,我制作了 C++ 容器底层数据的大量副本。例如,如果 c++ 库函数返回 a std::vector<int>,我的包装器将返回 形式的结构{size_t len; size_t size; void *arr;},其中arr包含向量中数据的副本。当用户使用完数据后,他们必须释放它。
我的问题是:用户(C 代码)调用C++ 中已 :d 的指针总是合法的吗?或者我必须在包装器代码中创建等效函数吗?free()malloc()
std::malloc和 Cfreestd::mallocC++ 中的定义<cstdlib>据说与 C 中具有相同的内容和含义<stdlib.h>(有一些变化,例如命名空间)。此外,[c.malloc]说:
Run Code Online (Sandbox Code Playgroud)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 标准库中指定的语义。
这意味着您可以std::malloc在 C++ 中分配一些内存,并将其传递给某个调用free.
注意:混合不同的标准库或混合同一标准库的不同构建(调试/发布)可能仍然是一个问题,但这适用于所有语言功能。
std::malloc话虽如此,使用像您建议的free那样分配的内存是不安全的。默认情况下,std::vector所有进行内存分配的容器都使用.std::allocatoroperator new
即使获取和释放内存的底层操作系统函数是相同的,混合new和也是未定义的行为。free
std::vector在C中使用// 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);
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,我们基本上只是定义了struct vector包含一定数量的字节的 a 和三个不透明函数。所有代码都是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(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);
}
Run Code Online (Sandbox Code Playgroud)
C++ 端使用std::construct_at(或者在 C++20 之前,您可以使用新的放置)。std::vector我们在 的原始字节中创建一个vector::data。请注意,我们没有在这段代码中
调用new、delete、malloc或。仍然负责所有的内存管理。freestd::vector
| 归档时间: |
|
| 查看次数: |
239 次 |
| 最近记录: |