用new重新分配内存是否安全
Is it safe to realloc memory allocated with new?
根据这里的内容,new
在自由存储中分配,而malloc
使用堆,这两个术语通常意味着相同的含义。
根据这里所写的内容,realloc
可以将存储器块移动到新的位置。如果空闲存储和堆是两个不同的内存空间,那么这意味着有什么问题吗?
具体来说,我想知道使用是否安全
int* data = new int[3];
// ...
int* mydata = (int*)realloc(data,6*sizeof(int));
如果没有,是否有其他方法可以安全地使用new
分配realloc
内存?我可以分配新的区域和memcpy
的内容,但据我所知,如果可能的话,realloc
可能会使用相同的区域。
您只能通过malloc
(或系列,如calloc
)分配的realloc
。
这是因为跟踪可用和已用内存区域的底层数据结构可能截然不同。
这很可能是,但决不能保证C++new
和C malloc
使用相同的底层分配器,在这种情况下,realloc
可以同时适用于两者。但从形式上讲,那是在乌兰巴托。在实践中,这只是不必要的风险。
C++不提供与CCD_ 14相对应的功能。
最接近的是像std::vector
这样的容器(的内部缓冲区)的自动重新分配。
C++容器的设计方式排除了CCD_ 16的使用。
代替呈现的代码
int* data = new int[3];
//...
int* mydata = (int*)realloc(data,6*sizeof(int));
…这样做:
vector<int> data( 3 );
//...
data.resize( 6 );
然而,如果你绝对需要realloc
的一般效率,并且你必须接受new
作为原始分配,那么你唯一的效率途径就是使用编译器特定的方法,知道realloc
使用这个编译器是安全的。
否则,如果您绝对需要realloc
的一般效率,但不被迫接受new
,那么您可以使用malloc
和realloc
。使用智能指针可以获得与C++容器相同的安全性。
C++对realloc
添加的唯一可能相关的限制是,C++的malloc
/calloc
/realloc
不得根据::operator new
实现,其free
不得根据::operator delete
实现(根据C++14[C.malloc]p3-4)。
这意味着您正在寻找的保证在C++中不存在。但是,这也意味着您可以根据malloc
来实现::operator new
。如果你这样做,那么理论上,::operator new
的结果可以传递给realloc
。
在实践中,您应该关注new
的结果与::operator new
的结果不匹配的可能性。C++编译器可以例如组合多个CCD_ 37表达式以使用单个CCD_。这是编译器在标准不允许的时候已经做过的事情,IIRC,现在标准允许了(根据C++14[expr.new]p10)。这意味着即使你走这条路,你仍然不能保证将new
指针传递给realloc
会有任何意义,即使它不再是未定义的行为。
一般情况下,不要这样做。如果您使用带有非平凡初始化的用户定义类型,则在重新分配副本释放的情况下,realloc
不会调用对象的析构函数。复制时,复制构造函数也不会被调用。由于不正确使用对象生存期,这可能导致未定义的行为(请参见C++标准§3.8对象生存期,[basic.life])。
1对象的生存期是该对象的运行时属性。如果一个对象是类或聚合类型,并且它或它的一个成员是由非平凡默认构造函数初始化的,则称其具有非平凡初始化。[注意:由琐碎的复制/移动构造函数初始化是非琐碎的初始化。--结束注释]
T型物体的寿命开始于:
--获得了具有适当排列和尺寸的T型存储器,并且
--如果对象进行了非平凡的初始化,那么它的初始化就完成了。
T类型对象的寿命在以下情况下结束:
--如果T是具有非平凡析构函数(12.4)的类类型,则析构函数调用启动,或者
--对象占用的存储器被重新使用或释放。
后来(重点是我的):
3本国际标准中赋予物体的特性仅适用于给定物体的使用寿命。
因此,您真的不想在对象生命周期结束后使用它。
它不安全,也不优雅。
可以覆盖new/delete以支持重新分配,但您也可以考虑使用容器。
一般来说,没有
有很多东西必须保持安全:
- 逐位复制类型并放弃源必须是安全的
- 析构函数必须是琐碎的,或者必须对要解除分配的元素进行原位析构函数
- 构造函数要么是琐碎的,要么必须就地构造新元素
琐碎的类型满足上述要求。
此外:
new[]
-函数必须在没有任何更改的情况下将请求传递给malloc
,也不能在一旁进行任何记账。您可以通过替换全局new[]和delete[],或者替换相应类中的全局new[]或delete[]来强制执行此操作- 编译器不能为了保存分配的元素数量或其他任何东西而要求更多的内存
没有办法强制这样做,尽管如果类型有一个微不足道的析构函数,编译器不应该保存这样的信息,这是实现质量的问题
是-如果new
实际上首先调用了malloc
(例如,VC++new
就是这样工作的)。
否则不会。请注意,一旦您决定重新分配内存(因为new
称为malloc
),您的代码是特定于编译器的,不再可在编译器之间移植。
(我知道这个答案可能会让很多开发人员感到不安,但我的答案取决于真实的事实,而不仅仅是惯用的)。
这是不安全的。首先,您传递给realloc
的指针必须是从malloc
或realloc
获得的:http://en.cppreference.com/w/cpp/memory/c/realloc.
其次,new int [3]
的结果不必与分配函数的结果相同——可以分配额外的空间来存储元素的计数。
(对于比int
更复杂的类型,realloc
是不安全的,因为它不调用复制或移动构造函数。)
您可能可以(并非在所有情况下),但不应该。如果需要调整数据表的大小,则应使用std::vector
。
关于如何使用它的详细信息在另一个SO问题中列出。
这些函数主要用于C.
memset将内存块中的字节设置为特定值。
malloc分配一块内存。
胼胝体,与malloc相同。唯一的区别是它将字节初始化为零。
在C++中,分配内存的首选方法是使用new。
C: int intArray=(int*)malloc(10*sizeof(int));C++:int intArray=new int[10];
C: int intArray=(int*)calloc(10*sizeof(int));C++:int intArray=new int10;
- 我在 IDA 或 dbg 或 olly 上看到的内存是否与我在 RAM 上实时加载的内存相同?
- 访问"std::vector"的保留但未调整大小的内存作为原始内存是否安全?
- 本地分配的内存是否可以用于将来使用?
- 多次分配内存是否一次性需要更多时间?
- 删除矢量的尾部(通过擦除)内存是否有效
- 如何找出内存是否属于堆或堆栈
- C++:提升:托管共享内存是否需要信号量锁
- 在 C/C++ 中在特定地址边界上对齐内存是否仍能提高 x86 性能?
- 检查内存是否在堆上
- C++内存 - 是否需要删除使用 'new' 创建的基元类型变量?
- 如果通过委托给“malloc”的重载“new[]”分配,“释放”内存是否安全
- 分配给 cpp 中定义的全局静态变量的内存是否在 C++ 中删除其类的实例后释放
- 我的 265GB RAM 笔记本电脑上的内存是否超过 8GB
- 在动态内存分配中,在程序终止并且忘记释放内存后,该内存是否保持分配状态
- 这些二维数组(C++)的内存是否不足
- 如果我在 for 中声明一个对象,它的内存是否会在那之后被释放?
- 二进制搜索树(如何在插入时检查内存是否不足)
- 用new重新分配内存是否安全
- 在构造函数初始化列表中分配内存是否存在任何问题
- 内存映射内存是否可能