繁体   English   中英

使用memset而不是for循环初始化int **时出现分段错误

[英]Segmentation fault on using memset instead of for loops to initialize int**

这是我在c ++中的代码

int** a;
try{
  a = new int*[m];
  for(int i = 0; i<m;i++)
    a[i] = new int[n];
}

...现在我正在使用for循环初始化上面的内容,如下所示:

for(int i = 0; i<m; i++)
  for(int j = 0; i<n; j++)
      a[i][j] = 0;

我正在努力提高性能,因此使用memset的想法是个好主意。 所以修改我的代码使用memset而不是for循环,如下所示:

memset(a, 0, sizeof(a[0][0]) * m * n);

但是我在执行此操作时遇到Segmentation错误。 任何人都可以帮我弄清楚我做错了什么?

int** a;

这只是给你一个对象。 一个int**对象。 它根本不指向任何地方。 没有要分配的int 当您开始分配int ,就好像它们存在一样,您会得到未定义的行为。

此外,一个的存储器布局int**指向的“二维数组” int s是像这样:在int**在阵列的第一个元素点int* s,并且int* s的点int数组中的第一个元素。 这个内存不是连续的,因为它需要间接跳转内存,即它不是单个内存块。 你不能只使用memset写它。

如果您只想要一个固定的编译时大小的int数组,请执行以下操作:

int a[N][M];

其中NM是常量表达式。 连续存储的,但我仍然不建议使用memset

或使用标准容器,例如:

std::array<std::array<int, M>, N> a;

如果您需要动态大小,请尝试:

std::vector<std::vector<int>> a(M, std::vector<int>(N));

或者,您可以坚持使用int**并确保动态分配int* s和int s:

int** a = new int*[M];
for (i = 0; i < N; i++) {
  a[i] = new int[N];
}

但这太丑了!

int** a;

只是指向int的指针的声明。

“现在我正在使用for循环初始化上面的内容”

您没有在for循环中初始化它,您只是尝试将0分配给不存在的元素,这会产生未定义的行为 您需要为这些元素动态分配内存,或者甚至更好:使用std::vector代替:

std::vector< std::vector<int> > a(m, std::vector<int>(n, 0));

“我正在努力改善表现”

除非有必要,否则不要这样做。 不要过早优化。


编辑 :在你提到你已经面临性能问题之后,这就是你可以做的:而不是这个二维C风格的数组:

int** a = new int*[m];      // m = number of rows
for(int i = 0; i < m; i++)
    a[i] = new int[n];      // n = number of columns

你可以使用一维std::vector

std::vector<int> vec(rows * cols, 0);
...
vec[i * cols + j] = 7;   // equivalent of vec[i][j]
这将有更多的优势:
  • 您的2D数组将存储在连续的内存块中
  • 这块内存将立即分配,而不是分成许多小块
  • 由于空间局部性,频繁访问元素将更快
    (“靠近”的元素将在缓存中提供,因此您的
    程序不必从主内存加载它们)
  • 并且您不负责内存管理
    (一旦vector对象被破坏,内存将自动清理)

使用int ** ,通常不会有一个连续的内存块。 假设你正确使用它,你将有一个指针数组。 然后,每个指针都将分别为其分配一个数组。

在这种情况下,您无法将循环转换为单个memset (并且仍然可以获得定义的行为)。

我认为问题在于没有为实际存储分配内存。 变量a只是指针(另外没有初始化)。 它指向的地方?

你说你像这样分配了它:

a = new int*[m]; 
for(int i =0; i<m ;i++) a[i] = new int[n];

就像Je​​rry Conffin所说 - 这不会给你一个连续的内存块。 每个新数组( new int[n] )将分配在一个可能完全不同的位置,memset仅适用于连续的块,所以你必须“手动”重置每个数组顺便说一下 - 我很确定你不是将看到在循环中使用memset的任何性能改进(我认为memset本身使用循环实现)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM