简体   繁体   中英

Access violation writing error on writing to a 2D array after initializing using memset

I am using Visual Studio Community 2017.

Following the discussion below:

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

I have a 2 D matrix (10 x 10) that I initialize using memset . This is option 1.

Option 2 is initializing the same matrix using two for loops, each looping from 0 through 9.

Then, when I write to a valid matrix location, an access violation writing error is thrown when Option 1 was used. Everything works fine when Option 2 is used.

The minimal working code I have that replicates this is given below:

#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;
}

Any help is appreciated.

With the memset you're overriding the pointers returned by your memory allocations, therefore when you access the memory later you're actually deferring a null pointer.

Your 2D array is actually an array of pointers, so memory is not contiguous and you cannot do a memset to set it to 0. Technically, it is just a pointer and dynamically you allocate space for another 10 pointers, each of them pointing to 10 doubles.

Instead, use a double loop (nested-fors) to initialize it, or just one memset for each row:

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));

Also, if your array will always be 10x10 you can declare it instead as double cmatrix[10][10] : that memory is contiguous and you can do your original memset .

cmatrix is a array of pointers. A call of memset to zero on it, will in fact be setting all pointers to 0 (which is not what you want), which leads to the access violation later. For this kind of initialization I would choose the option 2 (the one in comments)

In this code:

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

you first allocate an array of 10 pointers to double ( double* ), and then, for each element (pointer) in this array, you allocate a new array of 10 double s.

Graphically:

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

You can't call memset to zero out this data structure, as you allocated scattered memory, instead a single call to memset requires contiguous memory.

You can do a simple memset invocation if you linearize the 2D array, ie allocating a single chunk of memory storing 10*10 = 100 double s, with a single call to new[] .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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