3

I'm attempting to allocate space for 100 doubles, check if the allocation was successful, and then deallocate the space. After that I'd like to use the original allocated space to write 100 random numbers to it and then sort them using qsort.

Here's the code I have to far

#include <stdio.h>
#include <stdlib.h>

int main()
{
    double *num = (double*) malloc(sizeof(double) * 100);

    printf("%lf", *num);

    realloc(num, 0);

    return 0;
}

When I attempt to print *num, it gives me 0.00000 which seems wrong. I get the warning

 warning: ignoring return value of function declared with
 'warn_unused_result' attribute [Wunused-result] realloc(num, 0);

when compiling the program. I'm still unsure on how to make this work with an array.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
  • 4
    you need to use `free` to deallocate the memory not `realloc`. – kiran Biradar Nov 06 '19 at 12:15
  • 3
    Memory allocated by `malloc` is not initialized, its contents is *indeterminate* and could be seen as random or garbage. And considering that there are many invalid bit combinations for floating point types in C, you could have *undefined behavior* accessing such a value. – Some programmer dude Nov 06 '19 at 12:17
  • 2
    And don't forget that `*num` is equal to `num[0]`. You check if an allocation was successful or not by checking the pointer that `malloc` returned to see if it's `NULL` or not, as in `if (num == NULL)`. – Some programmer dude Nov 06 '19 at 12:19
  • 1
    And talking about `malloc` and returns, in C you [don't need to cast the result of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc), and actually you *shouldn't* do that. – Some programmer dude Nov 06 '19 at 12:19
  • 4
    @kiran `realloc(ptr, 0);` and `free(ptr);` are equivalent. Like you, I prefer the later :) – pmg Nov 06 '19 at 12:19
  • 1
    As for the warning, the [`realloc`](https://en.cppreference.com/w/c/memory/realloc) function does what it name implies, it *reallocates* memory, and returns a pointer to the new memory. You don't do anything with the pointer `realloc` returns, so the compiler will (correctly) warn you about that. – Some programmer dude Nov 06 '19 at 12:22
  • 1
    "*... then deallocate it. After that I'd like to use the original allocated space*" you cannot use the memory any more, as you deallocated it already. – alk Nov 06 '19 at 12:25
  • 1
    In standard C, don't cast the return type of `malloc()`. If you need it, it means either that you have forgotten `` or that you are using a C++ compiler. It is not required with standard C, and is actively discouraged as bad practice. Also, if you deallocate memory (that was previously dynamlcally allocated) any usage of it gives undefined behaviour - it is necessary to reallocate it AND there is no guarantee the reallocation will give the same memory. ALWAYS check the return value from `malloc()` or `realloc()` - don't just assume they succeed. – Peter Nov 06 '19 at 12:27

2 Answers2

3

I think you are trying to do this:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    double *num = (double*) malloc(sizeof(double) * 100);

    if (num) {
        printf("SUCCESS!\n");

        for (int i = 0; i < 100; i++) {
            num[i] = rand();
        }

        /* sort here */

        free(num);
    } else {
        printf("FAILURE!\n");
    }

    return 0;
}
alk
  • 69,737
  • 10
  • 105
  • 255
  • 3
    This "*`printf("%lf", *num);`*" might very well still invoke undefined behaviour be reading out uninitialised memory. And if `malloc()` did fail then this line definitely invoked UB: `num[i] = rand();` by writing to invalid memory. – alk Nov 06 '19 at 12:26
  • @alk you are absolutely right. Already edited the code. Thank you. – Eduardo Fernandes Nov 06 '19 at 12:29
  • 3
    Now push the `for`-loop inside the `if`-section and you are fine. – alk Nov 06 '19 at 12:30
  • 1
    @EduardoFernandes - you need to do more. If `malloc()` fails (i.e. returns `NULL`) then the loop will give undefined behaviour, and your code doesn't (as yet) prevent that. – Peter Nov 06 '19 at 12:30
  • 1
    The `free()` could have stayed out side the `if` as doing `free(NULL)` simply does nothing (if not using a super super old compiler). – alk Nov 06 '19 at 12:33
  • 3
    To finally make this nice change `double *num = (double*) malloc(sizeof(double) * 100);` to be `double *num = malloc(100 * sizeof *num);`. :) – alk Nov 06 '19 at 12:37
  • 2
    @alk: it's even cooler when you add a space before the variable name, `malloc(100 * sizeof * num)`. On a more serious note though, I believe a good practice is to always put `sizeof` first, since in cases like `sizeof *x * rows * cols` it ensures that all multiplication is done with `size_t` width. Not important in this case, but many times working effectively with C is a matter of sticking to best practices. – vgru Nov 06 '19 at 13:26
3

It is bad practice to pass the value zero to the malloc family of functions. What happens then is implementation-defined, meaning that different compilers might give different results.

C17 7.22.3

If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.

This isn't normal use of realloc - normally the compiler expects you to use the return value. Hence the warning.

Forget about realloc(num, 0); and use free() instead.

Lundin
  • 195,001
  • 40
  • 254
  • 396