1

I am getting an exception when printing a two-dimensional array after initializing it using memset. If I initialize each element and then access it, then there is no error. Please help to figure out the bug in the code.

#include "stdafx.h"
#include "stdlib.h"
int r = 0;
int c = 0;
int **twoDArray() {

    int *arr[5];

    for (r = 0; r < 5; r++) {

        arr[r] = (int*)malloc(2 * sizeof(int));

    }
   // 
    for (r = 0; r < 5; r++) {
        for (c = 0; c < 2; c++) {
            arr[r][c] = 1;
            printf("%d \n", arr[r][c]);
        }
    }
    memset(arr, 0, 2 * 5 * sizeof(arr[0][0]));
    for (r = 0; r < 5; r++) {
        for (c = 0; c < 2; c++) {
            printf("%d \n", arr[r][c]); //getting exception here.
        }
    }
    return arr;

}


int main()
{
    int **arr;
    arr = twoDArray();
    for (r = 0; r < 5; r++) {
        for (c = 0; c < 2; c++) {
            arr[r][c] = 0;
            printf("%d \n", arr[r][c]);
        }
    }
    return 0;
}
1
  • Your program is broken regardless of whether you use memset or not. Your twoDArray function returns a pointer to a local array arr. The latter is automatically destroyed when the function exits. Trying to use the returned result in main triggers undefined behavior. Commented May 26, 2018 at 17:53

2 Answers 2

4

You don't have a 2D array. You have a 1D array of pointers to 1D arrays; each of these arrays can be (and 99.9% likely is) at a different address in memory. You therefore cannot treat them as one continuous block, as memset does.

The best (and most cache-friendly) option is to allocate the entire array dynamically:

int *arr = malloc(2 * 5 * sizeof(int));

This will require you to then do manual indexing:

for (r = 0; r < 5; r++) {
    for (c = 0; c < 2; c++) {
        arr[r * 2 + c] = 1;
        printf("%d \n", arr[r * 2 + c]);
    }
}

If you know the array size at compile time (if the 2 and 5 are actual constants), you can also make arr a pointer to an actual array, to allow syntactic 2D indexing:

typedef int Array[2];

Array *arr = malloc(5 * sizeof(Array));

for (r = 0; r < 5; r++) {
    for (c = 0; c < 2; c++) {
        arr[r][c] = 1;
        printf("%d \n", arr[r][c]);
    }
}

Note that in your original code, there was also the problem you were returning a pointer into arr, which is a local variable, making the pointer immediately dangling.

Sign up to request clarification or add additional context in comments.

Comments

3

This is an array of pointers. You can be sure of two things

  • arr[0] to arr[4] is contiguous.
  • The chunk allocated is contiguous.

But who told you that the memory block allocated by each malloc which each of the pointer points to is contiguous also? Nobody did. You assumed it wrong.

In your case that's definitely not the case. That's why you invoked undefined behavior by accessing memory out of bound. (in memset).

Do this though - it would work

int (*arr)[2];
arr = malloc(sizeof *arr * 5);
// do memset - it's fine.

Don't cast the return value of malloc. It's redundant.

Something like this in earlier case:-

                                  +-------------+
        +-------+         +------>+  arr[0][0]  |
arr[0]  |       |         |       |      |    arr[0][1]
        |   +-------------+       +------+------+
        +-------+
        |       |     +------+------+
arr[1]  |    +------->+      |      |
        +-------+     |      |      |
        |       |     +-------------+              +------+------+
arr[2]  |    +-------------------------------------+      |      |
        +-------+                                  |      |      |
        |     | |                 +------+------+  +------+------+
arr[3]  |     +------------------>+      |      |
        +-------+                 |      |      |
        |       |                 +------+------+
arr[4]  |    +  |
        +-------+
             |                        +------+------+
             +----------------------->+      |      |
                                      |      |      |
                                      +------+------+

3 Comments

#rez to myself for future.
@snr>; I am not sure what you mean...#rez?
I'm impressed your answer. #rez means I leave my comment here to glance at the answer in future.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.