-3

Let's start with the code:

#include <stdio.h>
#include <stdlib.h>
int main (void) {

    int** matrix;
    int n = 5;
    int m = 5;
    matrix = (int**)malloc(n*sizeof(int*));
    for (int i = 0; i < n; i++) {
        matrix[i] = (int*)malloc(m*sizeof(int*));
    } 

    //This works:
    matrix[4][90] = 50;
    printf("%d", matrix[4][90]);

    //This produces an error:
        //matrix[5][90] = 50;
        //printf("%d", matrix[5][90]);

    return 0;

}

I've been using this method to dynamically allocate memory for a 2d array (and I've seen a lot of people use it too) and it works great. However, recently I noticed that it seems to allocate more memory than intended and I can't understand why.

In the above example, I'm trying to create a 5x5 array. It creates exactly 5 rows (n) and gives you an error if you try to access any other than those rows. Working as intended. Great! However, it seems like it's creating a massive number of columns (m), when I only want it to create 5. Why is this, and how do I fix it?

Same thing seems to be true for calloc as well.

Thanks!

ckruczek
  • 2,361
  • 2
  • 20
  • 23
Lobs001
  • 365
  • 4
  • 14
  • 4
    It's not creating a massive number of columns. You access beyond the limit of the memory you allocated. That has undefined behavior. UB means it may *appear* to work. – StoryTeller - Unslander Monica Mar 24 '17 at 09:07
  • 1
    "//This produces an error: //matrix[5][90]" Arrays start with index zero in C. – Lundin Mar 24 '17 at 09:08
  • @Lundin Yes, I was trying to show that it was working as intended for the rows, but not the columns. So naturally [4] works while [5] shouldn't (and don't). – Lobs001 Mar 24 '17 at 09:13
  • 2
    *"while [5] shouldn't"* - Accessing via 5 is as UB as accessing via 90. There's no notion of should or shouldn't here. UB means your program is unreliable. – StoryTeller - Unslander Monica Mar 24 '17 at 09:16
  • @StoryTeller Thanks. I thought there was something wrong with the code. Didn't think of undefined behavior. – Lobs001 Mar 24 '17 at 09:28
  • 1
    Had this actually been a 2D array though, accessing item [90] would likely have caused you to get item [0] from the next row (not guaranteed by C but will work in practice). You are not allocating a 2D array though, you are allocating a fragmented look-up table thing. Read [Correctly allocating multi-dimensional arrays](http://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) to learn why this method is bad and slow. – Lundin Mar 24 '17 at 09:30
  • @Lundin Interesting read. Using that method vs the one I normally use probably won't have any significant impact on the things I'm currently doing, but it never hurts to do things a slightly better way instead of forming bad habits. :) – Lobs001 Mar 24 '17 at 09:47

1 Answers1

2

Change line :

matrix[i] = (int*)malloc(m*sizeof(int*));

to :

matrix[i] = (int*)malloc(m*sizeof(int));

as matrix[i] is of type int *, so the memory you allocate for it will contain int.

However, it seems like it's creating a massive number of columns (m), when I only want it to create 5

It is not. You invoke undefined behaviour by trying to access elements out of the bounds of your memory, so the first example you show works accidentally. Your code will create only 5 columns per row.

Marievi
  • 4,951
  • 1
  • 16
  • 33
  • Ah, that explains it. Thank you very much. I thought there was something wrong with the code and that's why it behaved so strangely. Still relatively new to C so it's hard to know what's undefined behavior and what's not. – Lobs001 Mar 24 '17 at 09:24
  • 1
    @Lobs001 here is a little help http://stackoverflow.com/documentation/c/364/undefined-behavior#t=201703240937511233433 – Kami Kaze Mar 24 '17 at 09:38