Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VS2019 C6011 Error Dereferencing Null Pointer 'NewNode'

Tags:

c

nullptr

Hello? I'm studying Doubly Linked List

Anyway, when I used to put data on node, there were C6011 error [:Dereferencing Null Pointer 'NewNode']

So I refered https://docs.microsoft.com/ko-kr/visualstudio/code-quality/c6011?view=vs-2019 and

tried to check null value. But It didn't work..

I checked some details on error window like picture I added

They said 'NewNode will be NULL', 'NewNode will be still NULL even if it is dereferenced'

enter image description here

Code is like below

1.header file(DoubleLinkedList.h)

#pragma once
#ifndef DOUBLY_LINKEDLIST_H
#define DOUBLY_LINKEDLIST_H

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef int ElementType;

typedef struct MyNode
{
    ElementType Data;
    struct MyNode* Prev;
    struct MyNode* Next;
}Node;

Node* DLL_CreateNode(ElementType NewData); //1.create node
void DLL_DestroyNode(Node* Node);//2.destroy node
void DLL_AppendNode(Node** Head, Node* NewNode);//3.append node
/*
4.insert node
connect
prev-insert-next  
*/
void DLL_InsertAfter(Node* Current, Node* NewNode);


void DLL_RemoveNode(Node** Head, Node* Remove);//5.remove node
Node* DLL_GetNodeAt(Node* Head, int location);//6.search node 
int DLL_GetNodeCount(Node* Head);//7.count the number of nodes
#endif

2.DLL.cpp(which is for header file)

#include "DoubleLinkedList.h"

Node* DLL_CreateNode(ElementType NewData)    
{
    //create node with memory allocation
    Node* NewNode = (Node*)malloc(sizeof(Node));

  //nullptr check for c6011(https://docs.microsoft.com/ko-kr/visualstudio/code-quality/c6011?)
    if (NewNode)
    {
        NewNode->Data = NewData;
        NewNode->Prev = NULL;
        NewNode->Next = NULL;
    }


    return NewNode;
}

void DLL_DestroyNode(Node* Node)
{
    free(Node);
}

void DLL_AppendNode(Node** Head, Node* NewNode)
{
    if ((*Head) == NULL)
    {
        *Head = NewNode;
    }
    else
    {
        Node* Tail = (*Head);

        while (Tail->Next != NULL)
        {
            Tail = Tail->Next;
        } 
        Tail->Next = NewNode;
        NewNode->Prev = Tail;
    }
}

void DLL_InsertAfter(Node* Current, Node* NewNode)
{

    NewNode->Prev = Current->Next;
    NewNode->Next = Current;

    if (Current->Next != NULL)
    {
        Current->Next->Prev = NewNode;
        Current->Next = NewNode;
    }
}

void DLL_RemoveNode(Node** Head, Node* Remove)
{

    if (*Head == Remove)
    {

        *Head = Remove->Next;
        if (*Head != NULL)
        {
            (*Head)->Prev = NULL;
        }
        Remove->Next = NULL;
        Remove->Prev = NULL;
    }
    else
    {
        Node* Temp = Remove;

        if (Remove->Prev != NULL)
        {

            Remove->Prev->Next = Temp->Next;
        }

        if (Remove->Next != NULL)
        {

            Remove->Next->Prev = Temp->Prev;
        }

        Remove->Prev = NULL;
        Remove->Next = NULL;
    }
}

Node* DLL_GetNodeAt(Node* Head, int location)
{
    Node* Current = Head;

    while (Current != NULL && (--location) >= 0)
    {
        //--location >=0 is for check index
        Current = Current->Next;
    }
    return Current;
}

int DLL_GetNodeCount(Node* Head)
{
    int count = 0;

    Node* Current = Head;

    while (Current != NULL)
    {
        Current = Current->Next;
        count++;
    }

    return count;
}

3.Practice file(.c)

#include "DoubleLinkedList.h"

int main()
{
    int i = 0;
    int Count = 0;
    Node* List = NULL;
    Node* Current = NULL;
    Node* NewNode = NULL;

   //create&append nodes
    for (i = 0; i < 5; i++) {
        NewNode = DLL_CreateNode(i);
        DLL_AppendNode(&List, NewNode);
    }


    Count = DLL_GetNodeCount(List);
    for (i = 0; i < Count; i++) {
        Current = DLL_GetNodeAt(List, i);
        printf("List[%d] : %d\n", i, Current->Data);
    }



    Current = DLL_GetNodeAt(List, 2);
    NewNode = DLL_CreateNode(3000);

    DLL_InsertAfter(Current, NewNode);

    Count = DLL_GetNodeCount(List);
    for (i = 0; i < Count; i++) {
        Current = DLL_GetNodeAt(List, i);
        printf("List[%d] : %d\n", i, Current->Data);
    }

    for (i = 0; i < Count; i++) {
        Current = DLL_GetNodeAt(List, 0);

        if (Current != NULL) {
            DLL_RemoveNode(&List, Current);
            DLL_DestroyNode(Current);
        }
    }

    return 0;
}

Thank you!

like image 358
정지수 Avatar asked Sep 29 '19 05:09

정지수


1 Answers

These is a warning from the static analyzer. The compiler says that there might be something potentially wrong.

And indeed, in DLL_CreateNode there is a call to malloc that could fail and return a NULL. You check it inside the function, which is fine.

But if malloc fails, you would still return a NULL to the caller in main.c.

NewNode = DLL_CreateNode(i);   //<-- this could return NULL
DLL_AppendNode(&List, NewNode);

In this case, this NULL would be given to DLL_AppendNode as the second parameter.

If there is an existing head node at this point in time, then in DLL_AppendNode at this line:

NewNode->Prev = Tail;

it would give an EXC_BAD_ACCESS exception.

The static analyzer has thus correctly identified a potential problem.

There are several ways to deal with it. One solution would be to check for NULL, print an error message on stderr, and exit the program with an error code.

like image 87
Stephan Schlecht Avatar answered Sep 30 '22 00:09

Stephan Schlecht