将 malloc/realloc 用于类/结构数组,包括 std 向量 [英] Using malloc/realloc for array of classes/structs including std vector
问题描述
我有一个关于 malloc/realloc 内存的问题,它将包含一个包含 std 向量的类/结构数组(我尝试了结构和类,但问题仍然存在)成员.我知道我可以通过使用 new 和 std 数组容器类来规避这个问题.但是,我想更好地理解为什么当我使用 realloc 而不是 malloc 时以下小代码会崩溃(因为我在将较大的代码项目从 C 转换为 C++ 的上下文中遇到了这个问题).似乎我也不一定能在类/结构中设置向量的初始大小(有些编译器允许有些不允许..)-那么类中的向量是什么-舒适的指针?
I have a question wrt malloc/realloc memory that will contain an array of class/struct (i tried both struct and class the issue remains) members that include std vectors. I know I can circumvent the problem by using new and std array container class. However, I'd like to better understand why the following little code crashes when I use realloc instead of malloc (as I encountered this problem in the context of transitioning a larger code project from C to C++). It also seems that I cannot necessarily set an initial size of a vector in a class/struct (some compilers allow some don't ..)- so what is a vector in a class - a comfortable pointer?
谢谢,凯
#include <stdlib.h>
#include <limits.h>
#include <float.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <sys/types.h>
#include <vector>
/* mpic++ -O3 -ffast-math -pedantic vec-alloc.cpp -o vec-alloc */
using namespace std;
class float_vector{
public:
double x;
double y;
double z;
float_vector() : x(0), y(0), z(0) {};
};
class voxel{
public:
float_vector x;
vector<double> y;
voxel() : x() {};
};
int main(){
int i;
double d =1.111;
voxel v0, *Comp, *Comp2;
/* dynamically allocate memory */
Comp= (voxel*)malloc(10*sizeof(voxel));
for(i=0;i<10;++i) Comp[i] = v0;
printf("malloc done\n");
/* dynamically re-allocate memory */
Comp2= (voxel*)malloc(sizeof(voxel));
printf("realloc done\n");
for(i=0;i<10;++i){
Comp2 =(voxel*)realloc(&Comp2[0], (i+1)*sizeof(voxel));
Comp2[i] = v0;
}
printf("realloc done\n");
for(i=0;i<10;++i) Comp[i].y.push_back(d);
for(i=0;i<10;++i) printf("%lf\n",Comp[i].y[0]);
for(i=0;i<10;++i) Comp2[i].y.push_back(d); // this crashes
for(i=0;i<10;++i) printf("%lf\n",Comp2[i].y[0]);
return 1;
}
推荐答案
如果将 malloc()
与非 POD 类一起使用,则必须调用构造函数(通过放置 new
) 和手动析构函数.
If you use malloc()
with non-POD classes, you must call constructors (via placement new
) and destructors manually.
使用未正确构造的对象会导致未定义行为,这通常意味着指针会崩溃.
Using an object which was not constructed properly results in undefined behavior, which often means a crash when it comes to pointers.
显然,在没有适当销毁对象的情况下为对象释放内存也会导致 UB.
Obviously, freeing a memory for object without a proper destruction of it causes UB too.
您的代码必须如下所示:
Your code must look like this:
MyClass *arr = (MyClass *) malloc(10 * sizeof (MyClass));
for (int i = 0; i < 10; i++)
new (arr + i) MyClass; // This line calls constructors
// Do something with the array here
for (int i = 0; i < 10; i++)
arr[i].~MyClass(); // This line calls destructors.
free(arr);
<小时>
这个要求也意味着你不能将 realloc()
用于非 POD 类型,因为它不会为你调用旧数组的析构函数和新数组的构造函数.
This requirement also means that you can't use realloc()
with non-POD types, because it wont call destructors for the old array and contructors for the new one for you.
手动重新分配代码可能如下所示:
Manual reallocation code might look like this:
MyClass *new_ptr = (MyClass *) malloc(new_size * sizeof (MyClass));
for (int i = 0; i < new_size; i++)
new (new_ptr + i) MyClass((MyClass &&) old_ptr[i]);
for (int i = new_size; i < old_size; i++)
new (new_ptr + i) MyClass;
for (int i = 0; i < old_size; i++)
old_ptr[i].~MyClass();
free(old_ptr);
<小时>
请记住,上面的代码并不是真正的异常安全.如果构造函数抛出异常并且您捕获了它,那么您要确保正确销毁已构造的对象.谢谢@SteveJessop.
现在当你明白为什么在 C++ 中通常应该避免 malloc()
/free()
时,我希望你会回到更安全的状态new
/delete
,它为你完成所有的构建和销毁.
Now when you understand why malloc()
/free()
usually should be avoided in C++, I hope you'll return to a lot more safe new
/delete
, which do all that construction and destruction for you.
这篇关于将 malloc/realloc 用于类/结构数组,包括 std 向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!