1

OK, I acknowledge that I should check for NULL pointer when mallocing, but what about calloc? Are there any memory leaks possible?

int **initializeMatrix(int *rows, int *cols) {
    int **matrix = malloc((*rows) * sizeof(int*));
    checkNullPointer(matrix);
    for(int i = 0; i < *rows; i++) {
        matrix[i] = calloc(*cols, sizeof(int));
    }

    return matrix;
}

void checkNullPointer(int **ptr) {
    if (ptr == NULL)
        printErrorMessage(memoryErrorMessage, 101);
}
tomashauser
  • 561
  • 3
  • 16
  • 3
    Why do you think it’s different with calloc? – Macmade Nov 25 '19 at 18:05
  • Nobody talks about it. When you are callocing the memory, it is set to some value, while when mallocing the memory gets reserved for use isn't it? – tomashauser Nov 25 '19 at 18:07
  • 1
    checking the return value of `malloc` and related has nothing to do with memory leaks. You check the pointer it returns to see if the operation was successful or not. – yano Nov 25 '19 at 18:08
  • `When you are callocing the memory is set to some value,` and where from calloc does magically take this memory for zeroing? calloc is just malloc + memset – 0___________ Nov 25 '19 at 18:08
  • OK, so the checking for NULL pointer is because when I'll be freeing the memory at the end of the code, I'll not free the NULL pointer which would lead into some serious issues, right? – tomashauser Nov 25 '19 at 18:11
  • @tomashauser: There's no need to free a NULL pointer since it doesn't point to anything. – Bathsheba Nov 25 '19 at 18:12
  • It is undefined behaviour. Same as spending not your money. You can go to jail or even worse if it is the mafia money – 0___________ Nov 25 '19 at 18:14
  • If you didn't check for it, you wouldn't know that it's NULL and you'd free it as every other pointer, thus the error will occur. – tomashauser Nov 25 '19 at 18:14
  • 4
    @P__J__: U wot? `free(NULL)` has been defined as a no-op since ANSI C. – Bathsheba Nov 25 '19 at 18:16
  • @Bathsheba - I wrote about using NULL pointer – 0___________ Nov 25 '19 at 18:16
  • 1
    Note that you are not allocating a 2-dimensional array. You are allocating an array of pointers to multiple, completely separate 1-dimensionally arrays. That's a highly inefficient way to allocate memory, especially for "arrays" with more than two dimensions. See https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays – Andrew Henle Nov 25 '19 at 18:24
  • `calloc` [documentation](https://pubs.opengroup.org/onlinepubs/009695399/functions/calloc.html). – Neil Nov 25 '19 at 19:56
  • `malloc`, `calloc`, and `realloc` can all potentially return `NULL` if an allocation request cannot be satisfied, so yes, you should check the result of all of them. – John Bode Nov 25 '19 at 21:07

2 Answers2

1

You do indeed need to check the return value of calloc (it will be NULL if memory could not be allocated), but note that calling free on a NULL pointer is a no-op, so there is no immediate memory leak per se.

Of course, when cleaning up after encountering a NULL return, you'll need to call free on all non-NULL pointers emanating from successful calloc calls. Personally I'd call calloc on the row allocation too to make that process simpler.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • So in every iteration, I should do `checkNullPointer(matrix[i]);`, is that right? – tomashauser Nov 25 '19 at 18:09
  • @tomashauser: Well, you'll need a version of that with the appropriate pointer type: your pointer will be an `int *` type, although to be honest you could rewrite it taking `void*`, so you can use it for both cases. – Bathsheba Nov 25 '19 at 18:10
  • Oh, I see. I think I'll just do `if (matrix[i] == NULL) {...}`. – tomashauser Nov 25 '19 at 18:13
  • @tomashauser: No, `free` contains that `if` statement implicitly. – Bathsheba Nov 25 '19 at 18:13
  • What do you mean by that? `matrix[i]` is now a pointer which I am checking for being NULL. Next I'll free everything else but this pointer. – tomashauser Nov 25 '19 at 18:20
1

I think you do not understand what the calloc is.

Logical equivalent:

void *mycalloc(size_t num, size_t size)
{
    size_t total = size * num;
    void *ptr = malloc(total);
    if(ptr)
    {
        memset(ptr, 0, total);
    }
    return ptr;
}

You need to check if the memory was allocated exactly the same way as when usung malloc.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • I haven't heard of memset. I just thought that calloc will do malloc and assign zeroes in the designated memory space. But I didn't know that the NULL pointer checking was for failing to allocate the memory which could happen as well when callocing. – tomashauser Nov 25 '19 at 18:17
  • Well I'm obviously learning C and there are things which I can't find anywhere or deduce myself, so I ask here. It's not like asking how calloc works. This is a concrete problem which I stumbled upon. – tomashauser Nov 25 '19 at 19:10
  • There's a typo in the return type of `mycalloc`. Obviously, it should return `void *`. – Ian Abbott Nov 25 '19 at 19:12