1

Let's suppose I am trying to write a function that creates a simple linked list in C.

The function is like this:

node* createLinkedList(int n) {

    int i = 0;
    node* head = NULL;
    node* temp = NULL;
    node* p = NULL;

    for (i = 0; i < n; i++) {

        //create isolated node

        temp = malloc(sizeof(node));
        printf_s("\nEnter the data for node number %i:", i);
        scanf_s("%d", &(temp->data));
        temp->next = NULL;

        if (head == NULL) {
            //if list is empty then make temp as first node
            head = temp;
        }
        else {
            p = head;
            while (p->next != NULL)
                p = p->next;
            p->next = temp;
        }
    }
    return head;
}

If I purposely delete the line temp = malloc(sizeof(node)); the program compile just fine but I get a runtime error (obviously).

My question is: Shouldn't the compiler warn me that I did not allocate memory for the temp variable? Is it allocating that memory implicitly? If so, how?

Daniel Zardo
  • 127
  • 6
  • 1
    The compiler will warn you on an uninitialized usage: `node *temp;` ... `scanf_s("%d", &(temp->data));` but this is not the case, `temp` is used initialized even removing the `malloc` line. – David Ranieri Oct 13 '20 at 15:24
  • You want a static analyzer, in this case a tool like `cppcheck` will return `error: NULL pointer dereference` or something like that. – David Ranieri Oct 13 '20 at 15:39
  • 1
    OT: `scanf_s()`? `printf_s()`? Both `scanf()` and `printf()` are standard functions that ***MUST*** be implemented per the C standard. No one has "deprecated" them but Microsoft, and using them makes your code non-portable. And no, Microsoft's "improved" functions aren't any safer. – Andrew Henle Oct 13 '20 at 16:15
  • @AndrewHenle Amen to that. I tried implementing `gets_s` and the process was ... interesting ... https://stackoverflow.com/a/62976484/6699433 – klutt Oct 13 '20 at 16:57
  • @AndrewHenle I know that but Visual Studio was not compiling the code without scanf_s () and printf_s(). I do not know why maybe some configuration that I should have done and did not. – Daniel Zardo Oct 13 '20 at 19:56

2 Answers2

2

By definition, malloc doesn't allocate memory implicitly. It's the purpose of this function to return a valid memory address, which obviously can't be verified by the compiler as it will be called during runtime.

At this point, the compiler just assumes that the pointer is a valid one. It can't guess if the pointer is already pointing to a valid memory address or not.

  • Ok I get that, but I just find it weird that the compiler is not able to detect that there is not a allocation of memory in the code (which will certainly generate a runtime error). – Daniel Zardo Oct 13 '20 at 15:22
  • 1
    @DanielZardo There are many different ways that a pointer can be given a non-NULL value. `malloc` is just one of them. It's up to you to make sure that the pointer has a valid value before it's dereferenced. As an example, you aren't using `malloc` to assign a value to `head`, yet you don't expect and don't want the compiler to give you an error for that. – user3386109 Oct 13 '20 at 15:27
2

Shouldn't the compiler warn me that I did not allocate memory for the temp variable?

Nope. The allocation is done during runtime. The best the compiler can do is to warn you if an variable is not initialized. And this is the reason why I think it's a bad idea to initialize pointers to NULL;

$ cat main.c
int main(void)
{
    int *p;
    *p =42;
}

$ gcc main.c -Wall -Wextra
main.c: In function ‘main’:
main.c:4:8: warning: ‘p’ is used uninitialized in this function [-Wuninitialized]
    4 |     *p =42;
      |     ~~~^~~

If you change int *p; to int *p = NULL; you will not get that warning.

To simplify it a bit. The compiler has absolutely no idea whatsoever about allocation. The return value from malloc is simply an address. In that regard, these three statements are not fundamentally different:

int *p = NULL;
int *p = &k;
int *p = malloc(sizeof *p); 

In all three cases, p is assigned the value of an address. The compiler has no way to know if that address points to a valid memory address or not.

klutt
  • 30,332
  • 17
  • 55
  • 95