以下代码在删除时将导致核心转储。但是,如果注释掉“ memset”,则可以运行。 因此,似乎memset做错了。以下代码是什么问题?
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
int n= 5;
int **p = new int* [n];
for (int i=0; i<n; i++) {
p[i] = new int [n];
}
// if comment out this line, it is good to run.
memset(&p[0][0], 0, n*n*sizeof(int));
// core dump here
for (int i=0; i<n; i++) {
delete [] p[i];
}
delete [] p;
return 0;
}
答案 0 :(得分:3)
p[i]
中已分配的内存不一定是连续的。因此,调用memset
清除p[i]
中所有分配的内存将触及一部分不适合您的内存(造成分段错误的主要原因)。如果要将它们全部设置为零,则必须遍历它们:
for (int i=0; i<n; i++) {
memset(p[i], 0, n*sizeof(int));
}
答案 1 :(得分:1)
您创建的是指向非连续内存区域的指针数组
int **p = new int* [n];
for (int i=0; i<n; i++) {
p[i] = new int [n];
}
p[0]
指向第一个区域,p[1]
指向第二个区域,p[n]
指向最后一个区域。它们不是同一对象,因此从语言律师的角度来看,诸如memset
的呼叫是 未定义行为 。
memset(&p[0][0], 0, n*n*sizeof(int)); // Out of bound
&p[0][0]
指向n
个元素(大小为n*sizeof(int)
)的数组对象的第一个元素。违反规则后,发生任何奇怪的事情,中断的delete[]
调用就是对这种“内存损坏”的典型反应。
请注意,您不需要memset
即可在C ++中使用数组进行零初始化,只需在创建时对其进行初始化:
int **p = new int* [n];
for (int i=0; i<n; i++) {
p[i] = new int [n]();
}
如果您希望数组为连续的二维数组,其中每个子数组都与下一个相邻(标准工具均未提供),则可以使用“放置新方法”
int **p = new int* [n];
int *pool = new int [n*n]; // the whole array will be here
for (int i=0; i<n; i++) {
p[i] = new (pool + i*n) int [n]();
// Creating subobject arrays using placement parameter
// In this case parameter is a pointer to memory storage
// where new expression would create an object.
// No memory allocation is happening here.
}
....
delete [] p; // deleting array of pointers
delete [] pool; // deleting memory pool
或更妙的是,如果可能的话,请避免使用裸露的指针或使用户接触此类代码。使用标准库类型或您自己的类型的封装来隐藏该“代码戈尔”。这种公开代码的问题在于,如果有什么事情会中断执行,例如,没有任何程序可以释放内存。一个例外。
答案 2 :(得分:0)
将值ch转换为无符号char,并将其复制到dest所指向对象的每个第一个计数字符中。如果对象是可能重叠的子对象或不是TriviallyCopyable(例如,标量,C兼容结构或普通可复制类型的数组),则该行为是不确定的。 如果count大于dest指向的对象的大小,则行为是不确定的。
每次调用new
时,都会返回一个新的内存块。它不必完全在上一个块的后面。
因此,存储器不必像memset
那样必须是连续的,并且memset正在未分配给程序的存储器中写入,因此会发生崩溃。
要正确将内存初始化为零,请在新变量后添加括号:
int **p = new int* [n] (); // With C++11 and later can also be {}
for (int i=0; i<n; i++)
{
p[i] = new int [n] (); // With C++11 and later can also be {}
}