Open In App

Undefined Behavior in C and C++

When we run a code, sometimes we see absurd results instead of expected output. So, in C/C++ programming, undefined behavior means when the program fails to compile, or it may execute incorrectly, either crashes or generates incorrect results, or when it may fortuitously do exactly what the programmer intended. Whenever the result of an executing program is unpredictable, it is said to have undefined behavior. 

As a C programmer, understanding undefined behavior is very important for optimal coding and for the program to yield a good efficiency, especially when it comes to there are C codes embedded in system design.



Examples: 

Division By Zero

int val = 5;
return val / 0; // undefined behavior

Memory accesses outside of array bounds



int arr[4] = {0, 1, 2, 3};
return arr[5]; // undefined behavior for indexing out of bounds

Signed integer overflow

int x = INT_MAX;
printf("%d", x + 1); // undefined behavior

Null pointer dereference

val = 0;
int ptr = *val; // undefined behavior for dereferencing a null pointer

Modification of string literal

char* s = "geeksforgeeks";
s[0] = 'e'; // undefined behavior

Accessing a NULL Pointer, etc.

int* ptr = NULL;
printf("%d", *ptr); // undefined behavior for accessing NULL Pointer

Sometimes compilers may diagnose simple errors, however, sometimes they are not designed to diagnose the undefined behavior.

Following are some C/C++ programs that showcase undefined behavior:

Program 1:




// C++ Program to demonstrate
// division by 0
  
#include <iostream>
using namespace std;
  
int main()
{
    int x = 25, y = 0;
    int z = x / y;
    
    cout << z;
    
    return 0;
}
  
// This code is contributed by sarajadhav12052009




// C Program to demonstrate
// division by 0
  
#include <stdio.h>
  
// Driver Code
int main()
{
    int x = 25, y = 0;
    int z = x / y;
    printf("%d", z);
    return 0;
}

Program 2:




// C++ Program to demonstrate
// Uninitialized variables
  
#include <iostream>
using namespace std;
  
int main()
{
    bool val;
    
    if (val)
        printf("TRUE");
    else
        printf("FALSE");
}
  
// This is contributed by sarajadhav12052009




// C Program to demonstrate
// Uninitialized variables
  
#include <stdio.h>
  
// Driver Code
int main(void)
{
    typedef enum {False, True} bool;
      
    bool val;
    
    if (val)
        printf("TRUE");
    else
        printf("FALSE");
}

Program 3:




// C++ Program to demonstrate
// accessing value of NULL pointer
  
#include <iostream>
using namespace std;
  
int main()
{
    int* ptr = NULL;
    
    cout << *ptr;
    
    return 0;
}
  
// This code is contributed by sarajadhav12052009




// C Program to demonstrate
// accessing value of NULL
// pointer
  
#include <stdio.h>
  
// Driver Code
int main()
{
    int* ptr = NULL;
    printf("%d", *ptr);
    return 0;
}

Program 4:




// C++ program to demonstrate
// accessing out of bound
  
#include <iostream>
using namespace std;
  
int main()
{
    int arr[5];
  
    // We access arr[5] in last iteration.
    for (int i = 0; i <= 5; i++)
        cout << arr[i];
    
    return 0;
}
  
// This code is contributed by sarajadhav12052009




// C program to demonstrate
// accessing out of bound
  
#include <stdio.h>
  
// Driver Code
int main()
{
    int arr[5];
  
    // We access arr[5] in last iteration.
    for (int i = 0; i <= 5; i++)
        printf("%d ", arr[i]);
  return 0;
  //edited by malav.shubham17
}

Program 5:




// C++ Program to demonstrate going
// beyond limit of signed int
  
#include <iostream>
#include <climits>
using namespace std;
  
int main()
{
    int x = INT_MAX;
    
    cout << x + 1;;
    
    return 0;
}
  
// This code is contributed by sarajadhav12052009




// C Program to demonstrate going
// beyond limit of signed int
  
#include <stdio.h>
#include <limits.h>
  
// Driver Code
int main()
{
    int x = INT_MAX;
    printf("%d", x + 1);
    return 0;
}

Program 6:




// C++ Program to demonstrate trying to
// modify a string literal
  
#include <iostream>
using namespace std;
  
int main()
{
    char* s = "geeksforgeeks";
    
    s[0] = 'e';
    
    return 0;
}
  
// This code is contributed by sarajadhav12052009




// C Program to demonstrate trying to
// modify a string literal
  
#include <stdio.h>
  
// Driver Code
int main()
{
    char* s = "geeksforgeeks";
    s[0] = 'e';
    return 0;
}

program 7:




// c++ program to demonstrate undefined behavior
// of combination of post and pre increment
  
#include <iostream>
using namespace std;
  
int main()
{
    // code
    int p = 4;
  
    cout << ++p * p++ << endl;
  
    return 0;
}




// c program to demonstrate undefined behavior
// of combination of post and pre increment
  
#include <stdio.h>
  
int main()
{
    // code
    int p = 4;
  
    printf("%d", ++p * p++);
  
    return 0;
}

Output
30

Program:8




// c++ program to demonstrate undefined behavior
// of combination of post and post increment
#include <iostream>
using namespace std;
  
int main()
{
    // code
    int p = 4;
    cout << ++p * ++p;
    return 0;
}




// c program to demonstrate undefined behavior
// of combination of post and post increment
  
#include <stdio.h>
  
int main()
{
    // code
    int p = 4;
    printf("%d", ++p * ++p);
    return 0;
}

Output
36

Program 9:




// C++ Program to demonstrate modifying a variable
// multiple times before a defined sequence point
  
#include <iostream>
using namespace std;
  
int main()
{
    int i = 8;
    
    int p = i++ * i++;
    
    cout << p;
}
  
// This code is contributed by sarajadhav12052009




// C Program to demonstrate modifying a variable
// multiple times before a defined
// sequence point
  
#include <stdio.h>
  
// Driver Code
int main()
{
    int i = 8;
    int p = i++ * i++;
    printf("%d\n", p);
}

Output
72

Explanation: The program produces 72 as output in most of the compilers, but implementing software based on this assumption is not a good idea. 

The output of all of the above programs is unpredictable (or undefined). The compilers (implementing the C/C++ standard) are free to do anything as these are undefined by the C and C++ standards. 
Language like Java, trap errors as soon as they are found but languages like C and C++ in a few cases keep on executing the code in a faulty manner which may result in unpredictable results. The program can crash with any type of error message, or it can unknowingly corrupt the data which is a grave issue to deal with. 

Importance of knowing about Undefined Behaviour: If a user starts learning in a C/C++ environment and is unclear about the concept of undefined behavior then that can bring plenty of problems in the future while debugging someone else’s code might be actually difficult in tracing the root to the undefined error.

Risks and Disadvantages of Undefined Behaviour 

Advantages of Undefined Behaviour 

More Examples of undefined behavior  

  1. Sequence Points in C | Set 1
  2. “delete this” in C++
  3. Passing NULL to printf in C
  4. Accessing array out of bounds in C/C++
  5. Use of realloc()
  6. Execution of printf with ++ operatorsVirtual destruction using shared_ptr in C++
  7. Virtual Destructor

Article Tags :