使用memset初始化后写入2D阵列时出现访问冲突写入错误

时间:2017-09-21 10:22:29

标签: c++ memset

我正在使用2017年的Visual Studio社区。

按照以下讨论:

Fastest way to zero out a 2d array in C?

我有一个2 D矩阵(10 x 10),我使用memset进行初始化。这是选项1.

选项2使用两个for循环初始化相同的矩阵,每个循环从0到9循环。

然后,当我写入有效的矩阵位置时,使用选项1时会引发访问冲突写入错误。使用选项2时,一切正常。

我复制的最小工作代码如下:

#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
#include <math.h>
#include <cmath>
#include <vector>
#include <string>
#include <limits.h>
#include <stdlib.h>
#include <array> 



int main(){
    double ** cmatrix = new double*[10];
    for (int i = 0; i < 10; i++)
        cmatrix[i] = new double[10];

    memset(cmatrix, 0, 10 * 10 * sizeof(double));//Option 1    

    //for (int i = 0; i < 10; i++)//Option 2
        //for (int j = 0; j < 10; j++)
            //cmatrix[i][j] = 0;

    cmatrix[0][1] = 5;//This step produces error on Option 1, but not on option 2

    return 0;
}

感谢任何帮助。

3 个答案:

答案 0 :(得分:3)

使用memset覆盖内存分配返回的指针,因此当您稍后访问内存时,实际上是推迟了空指针。

您的2D数组实际上是一个指针数组,因此内存不是连续的,您无法将memset设置为0.从技术上讲,它只是一个指针并动态地为另外10个指针分配空间,他们每个都指向10个双打。

相反,使用双循环(嵌套fors)来初始化它,或者每行只使用一个memset

for (int i = 0; i < 10; ++i)
  for (int j = 0; j < 10; ++j)
    cmatrix[i][j] = 0.0;

// or

for (int i = 0; i < 10; ++i)
  memset(cmatrix[i], 0, 10 * sizeof(double));

此外,如果您的数组总是10x10,则可以将其声明为double cmatrix[10][10]:该内存是连续的,您可以执行原始memset

答案 1 :(得分:2)

cmatrix是一个指针数组。 调用memset为零,实际上将所有指针都设置为0(这不是你想要的),这会导致以后的访问冲突。 对于这种初始化,我会选择选项2(注释中的那个)

答案 2 :(得分:2)

在此代码中:

double ** cmatrix = new double*[10];
for (int i = 0; i < 10; i++)
    cmatrix[i] = new double[10];

首先将10个指针的数组分配给doubledouble*),然后将分配给每个元素(指针)数组,您分配一个10 double数组。

图形:

 array of 
 double*
   ||
   \/
+------+
|  x----------->   [0|1|... <10 doubles> ...|9]
+------+
|  x----------->   [0|1|... <10 doubles> ...|9]
+------+
| ...  |
+------+
|  x----------->   [0|1|... <10 doubles> ...|9]
+------+

您无法调用memset将此数据结构清零,因为您分配了分散的内存,而只需调用memset 连续记忆。

如果你线性化 2D数组,你可以做一个简单的memset调用,即分配一个存储10 * 10 = 100 double s的单块内存,单次拨打new[]