Category: C++ Advanced

https://zain.sweetdishy.com/wp-content/uploads/2026/02/Advanced.png

  • Chain of Responsibility in C++

    The Chain of Responsibility pattern is a behavioral design pattern which allows you pass a object of a request through a chain of potential handlers until one of them handles the request. This pattern decouples the sender of a request from its receiver by giving multiple objects a chance to handle the request.

    In this pattern, each handler in the chain has a reference to the next handler. When a request is received, the handler decides either to process the request or to pass it to the next handler in the chain. This continues until a handler processes the request or the end of the chain is reached.

    Chain of Responsibility Pattern Diagram

    Components of the Chain of Responsibility Pattern

    There are three main components in the Chain of Responsibility pattern, we have listed them below −

    • Handler − It can be an abstract class or it may be an interface which defines a method for handling requests and a method for setting the next handler in the chain.
    • Concrete Handler − These are the classes that implement the handler interface and provide specific implementations for handling requests. Each concrete handler decides whether to process the request or pass it to the next handler.
    • Client − The client is responsible for creating the chain of handlers and initiating the request processing by sending the request to the first handler in the chain.

    Implementation of the Chain of Responsibility Pattern

    Now, let’s implement the Chain of Responsibility pattern in C++.

    In this example, we will take an real-world scenario where, we have a support ticket system. The tickets can be handled by different levels of support staff based on the priority and complexity of the issue.

    Steps to Implement the Chain of Responsibility Pattern in C++

    Following are the steps to implement the Chain of Responsibility pattern in C++:

    Steps to Implement Chain of Responsibility Pattern

    C++ Implementation of Chain of Responsibility Pattern

    Here is a simple implementation of the Chain of Responsibility pattern in C++ of the support ticket system −

    #include <iostream>#include <string>usingnamespace std;// Abstract HandlerclassSupportHandler{protected:
       SupportHandler* nextHandler;public:SupportHandler():nextHandler(nullptr){}voidsetNextHandler(SupportHandler* handler){
          nextHandler = handler;}virtualvoidhandleRequest(const string& issue,int priority)=0;};// Concrete Handler: Level 1 SupportclassLevel1Support:public SupportHandler{public:voidhandleRequest(const string& issue,int priority)override{if(priority ==1){
             cout <<"Level 1 Support handled the issue: "<< issue << endl;}elseif(nextHandler){
             nextHandler->handleRequest(issue, priority);}}};// Concrete Handler: Level 2 SupportclassLevel2Support:public SupportHandler{public:voidhandleRequest(const string& issue,int priority)override{if(priority ==2){
             cout <<"Level 2 Support handled the issue: "<< issue << endl;}elseif(nextHandler){
             nextHandler->handleRequest(issue, priority);}}};// Concrete Handler: Level 3 SupportclassLevel3Support:public SupportHandler{public:voidhandleRequest(const string& issue,int priority)override{if(priority ==3){
             cout <<"Level 3 Support handled the issue: "<< issue << endl;}elseif(nextHandler){
             nextHandler->handleRequest(issue, priority);}}};intmain(){// Create handlers
       Level1Support level1;
       Level2Support level2;
       Level3Support level3;// Set up the chain of responsibility
       level1.setNextHandler(&level2);
       level2.setNextHandler(&level3);// Create some support requests
       level1.handleRequest("Password reset",1);
       level1.handleRequest("Software installation",2);
       level1.handleRequest("System crash",3);
       level1.handleRequest("Unknown issue",4);// No handler for this priorityreturn0;}

    In this example, we have defined an abstract handler class SupportHandler with a method to handle requests and a method to set the next handler. We then created three concrete handlers: Level1SupportLevel2Support, and Level3Support, each responsible for handling requests of different priority levels.

    In the main function, we created instances of each handler and set up the chain of responsibility. Finally, we created some support requests with different priority levels to demonstrate how the requests are handled by the appropriate handlers in the chain.

    Pros and Cons of Chain of Responsibility Pattern

    Here are some pros and cons of using the Chain of Responsibility pattern −

    ProsCons
    Makes it easy to separate who sends a request from who handles itCan be tricky to figure out where a request was handled
    Lets you add or remove support levels without much hassleIf the chain gets too long, it might slow things down
    Simple to organize and keep your code tidySome requests might not get handled at all
    You can change the order of handlers whenever you needIt’s not always obvious how the request moves through the chain
    Each handler can focus on just one thingYou need to plan carefully how handlers work together
    You can reuse the same handler in different chainsHaving lots of handlers might use more memory

    Real-World Examples of Chain of Responsibility Pattern

    Here are some real-world examples where the Chain of Responsibility pattern is commonly used −

    • Event Handling in Apps − When you click a button or press a key, the event travels through a series of handlers. The first one that knows what to do with it takes care of it, just like passing a message down a line until someone responds.
    • Logging − When something happens in a program, a log message might go through several loggers—one for errors, one for warnings, one for info—until it finds the right place to be recorded.
    • Customer Support − If you’ve ever contacted customer support, you know your question might get passed from one person to another until someone can actually help you. That’s the chain of responsibility in action.
    • Web Requests − When you visit a website, your request can go through different steps—like checking if you’re logged in, filtering out bad requests, or adding extra info—before it gets to the part that shows you the page.

    Conclusion

    In this chapter, we’ve seen what the Chain of Responsibility pattern is, how it works, and how to use it in C++. It’s a handy way to keep your code flexible and easy to maintain by letting requests find the right handler without everyone needing to know about each other.

  • C++ unordered_multiset

    std::unordered_multiset

    An unordered_multiset is a container by the Standard Template Library (STL) in C++, which stores elements without any particular order and allows multiple occurrences or duplicate values of the same element. The <unordered_set> header file is used for both unordered_set and unordered_multiset containers.

    Syntax

    Here is the following syntax for declaring an unordered_multiset:

    #include <unordered_set>
    std::unordered_multiset<type> container_name;

    Here,

    Example to Create unordered_multiset

    The following example demonstrates how you can create an unordered multiset:

    #include <unordered_set>#include <iostream>#include <string>usingnamespace std;intmain(){// Declare unordered_multisets for integers and strings
        unordered_multiset<int> ums_int ={1,2,3,3};
        unordered_multiset<string> ums_str ={"apple","banana","apple"};// Display both sets together (merged display)
        cout <<"Merged unordered_multiset (Integers and Strings): ";for(constauto& elem : ums_int){
            cout << elem <<" ";}for(constauto& elem : ums_str){
            cout << elem <<" ";}
        cout << endl;return0;}

    Output

    Merged unordered_multiset (Integers and Strings): 3 3 2 1 banana apple apple
    

    Member Functions of unordered_multiset

    1. The insert() function

    The insert() function is used to add one or more elements to the unordered_multiset, allowing duplicity.

    Syntax

    unordered_multiset<type> ums;
    ums.insert(element);
    ums.insert({element1, element2,...});

    2. The find() function

    The find() function is used to check if an element exists in the unordered_multiset. It returns an iterator to the element if found; otherwise, it returns end().

    Syntax

    auto it = ums.find(element);// Returns iterator to element or ums.end()

    3. The count() function

    The count() function returns the number of occurrences of an element in the unordered_multiset. Since this function allows duplicacy, it will return the total count of that element in the container.

    Syntax

    size_t count = ums.count(element);// Returns number of occurrences of element

    4. The erase() function

    The erase() function removes one or more elements from the unordered_multiset. You can remove specific elements by value or use an iterator to remove a single element. For duplicates, only one occurrence will be removed for each call.

    Syntax

    ums.erase(element);// Removes one occurrence of element
    ums.erase(it);// Removes the element at iterator `it`
    ums.erase(ums.begin(), ums.end());// Removes all elements in the range

    5.The find() or count() function

    This function will check if an element exists in the container.

    Syntax

    list.count(element);// for lists
    string.count(substring);// for strings

    6. The size() function

    The size() function returns the number of elements currently in the unordered_multiset.

    Syntax

    size_t size = ums.size();// Returns the number of elements in the set

    7. The begin() and end() functions

    To iterate, you can use iterators or range-based loops over the elements in an unordered_multiset. begin() and end() are used for accessing the first and last elements.

    Syntax

    for(auto it = ums.begin(); it != ums.end();++it){// Access each element via *it}

    unordered_set Vs. unordered_multiset

    • unordered_set: A container that stores unique elements only, no duplicates are allowed.
    • unordered_multiset: A container that allows multiple occurrences (duplicates) of the same element.

    Average Time Complexity of unordered_multiset

    unordered_multiset is implemented using a hash table data structure. This results in fast access because elements are hashed into “buckets” based on their hash values. This unordered_multiset provides constant time complexity, i.e., O(1), for some generic operations like lookups, insertions, and deletions.

    Hash collisions lead to the worst time complexity O(n). This is because, in a collision, multiple elements are hashed into the same bucket, which results in a linear search through all the elements in that bucket. This overall results in a significant degradation of performance.

    Use Cases of unordered_multiset

    • It is used when you want to store multiple occurrences of the same element.
    • It is suitable for counting the frequency of items or when duplicates are required.
    • It is efficient for quick lookups and insertions with no need for sorting.
  • nullptr in C++

    The nullptr keyword in C++ represents a null pointer value which was earlier represented using NULL or 0. It was introduced in C++11 and is of type std::nullptr_t. The nullptr is a type-safe pointer that is implicitly convertible and can be compared to any pointer.

    The syntax for defining a nullptr is given below −

    int* ptr =nullptr;// ptr is a null pointer of type int*

    Example

    The following example demonstrates how to use nullptr in C++

    #include <iostream>usingnamespace std;intmain(){int*ptr =nullptr;// ptr is a null pointerif(ptr ==nullptr){
    		cout <<"Pointer is null."<< endl;}else{
    		cout <<"Pointer is not null."<< endl;}int x =10;
    	ptr =&x;if(ptr !=nullptr){
    		cout <<"Pointer now points to: "<<*ptr 
                 << endl;}return0;}

    The output of the above code is given below −

    Pointer is null.
    Pointer now points to: 10
    

    Why Do We Need nullptr?

    We need nullptr because of the following problems caused by using NULL or 0

    Ambiguity in Function Calling

    Calling a function with value ‘0’ to represent NULL creates an ambiguity because compiler treats ‘0’ as an integer value rather than a null pointer.

    In this example, we are calling display() function by passing value as ‘0’. It calls the function that has an int parameter rather than calling the function that has a pointer in its parameter.

    #include <iostream>usingnamespace std;voiddisplay(int n){
       cout <<"Calling display function with int"<< endl;}voiddisplay(int*p){
       cout <<"Calling display function with int*"<< endl;}intmain(){display(0);// Ambiguous call as Compiler treats 0 as integerreturn0;}

    The output of the above code is given below −

    Calling display function with int
    

    Solution: Below is the solution to above problem where we have used nullptr that calls the display() function that has a pointer in its parameter −

    #include <iostream>usingnamespace std;voiddisplay(int n){
       cout <<"Calling display function with int"<< endl;}voiddisplay(int*p){
       cout <<"Calling display function with int*"<< endl;}intmain(){display(nullptr);return0;}

    The output of the above code is given below −

    Calling display function with int*
    

    Problem in Function Overloading

    If you call an overloaded function with NULL value, it will cause a compilation error. The NULL is valid for both parameters that is int and int*. So, in this confusion compiler throws an error. Below is an example to demonstrate this problem.

    #include <iostream>usingnamespace std;classDemo{public:voidshow(int n){
    		cout <<"Calling show() function with int"<< endl;}voidshow(int*p){
    		cout <<"Calling show() function with int*"<< endl;}};intmain(){
    	Demo obj;// Ambiguous call with NULL
    	obj.show(NULL);return0;}

    The output of the above code is given below −

    main.cpp: In function 'int main()':
    main.cpp:22:17: error: call of overloaded 'show(NULL)' is ambiguous
       22 |         obj.show(NULL);
          |         ~~~~~~~~^~~~~~
    main.cpp:7:14: note: candidate: 'void Demo::show(int)'
        7 |         void show(int n)
          |              ^~~~
    main.cpp:12:14: note: candidate: 'void Demo::show(int*)'
       12 |         void show(int *p)
          |              ^~~~
    

    Solution: Below is the solution to above problem where we have used nullptr that calls the display() function that has a pointer in its parameter −

    #include <iostream>usingnamespace std;classDemo{public:voidshow(int n){
    		cout <<"Calling show() function with int"<< endl;}voidshow(int*p){
    		cout <<"Calling show() function with int*"<< endl;}};intmain(){
    	Demo obj;
    	obj.show(nullptr);// Correctly calls int* functionreturn0;}

    The output of the above code is given below −

    Calling show() function with int*
    

    Type-Safety Problem

    The NULL is treated as an integer since it is defined with ‘0’. It creates the same ambiguity as the above two problems. It is solved using nullptr because nullptr is type-safe unlike NULL and it is implicitly convertible to any pointer type.

    #include <iostream>usingnamespace std;intmain(){int* ptr =nullptr;
    
    	cout <<"Comparing with NULL"<< endl;if(ptr ==NULL){
    		cout <<"NULL is TRUE"<< endl;}else{
    		cout <<"NULL is FALSE"<< endl;}
    
    	cout <<"\nComparing with nullptr"<< endl;if(ptr ==nullptr){
    		cout <<"nullptr is TRUE"<< endl;}else{
    		cout <<"nullptr is FALSE"<< endl;}int value =0;// NULL will be treated as integer 0if(value ==NULL){
    		cout <<"value(0) = NULL is TRUE"<< endl;}return0;}

    The output of the above code is given below −

    main.cpp: In function 'int main()':
    main.cpp:24:22: warning: NULL used in arithmetic [-Wpointer-arith]
       24 |         if (value == NULL) 
          |                      ^~~~
    Comparing with NULL
    NULL is TRUE
    
    Comparing with nullptr
    nullptr is TRUE
    value(0) = NULL is TRUE
    

    NULL vs nullptr

    The difference between NULL and nullptr is mentioned in the table below −

    NULLnullptr
    It is an integer constant that represents either 0 or 0L. In C, it is represented as ((void*)0).It is a pointer literal of type std::nullptr_t.
    It is not type-safe as it may be treated as an int.It is type-safe as it represents only pointer.
    It can be assigned to int values.It can not be assigned to an int value, as it will show an error.
    In function overloading, there is ambiguity when calling the function.It prevents the problem of ambiguity in function overloading.
    Example: int* p = NULL;Example: int* p = nullptr;

    Nullptr Use Cases

    The main purpose of the nullptr is to assign a null value to any pointer. Here are some use cases where a nullptr can be used.

    Resetting Pointers After Deletion

    A pointer needs to be assigned to a null value after deletion to avoid a dangling pointer. Here is an example to reset pointer to null after cleaning up the memory.

    #include <iostream>usingnamespace std;intmain(){int*ptr =newint(57);
    	cout <<"Value: "<<*ptr << endl;delete ptr;// Free memory
    	ptr =nullptr;// Resetting pointerif(ptr ==nullptr)
    		cout <<"Pointer reset successful."<< endl;return0;}

    The output of the above code is given below −

    Value: 57
    Pointer reset successful.
    

    Checking Pointer Validity

    You should first check that the pointer is not null before accessing it to avoid crashes. Here is an example to check if the pointer ptr is a null pointer or not.

    #include <iostream>usingnamespace std;intmain(){int*ptr =nullptr;if(ptr !=nullptr)
    		cout <<"Pointer value: "<<*ptr << endl;else
    		cout <<"It is a null pointer."<< endl;return0;}

    The output of the above code is given below −

    It is a null pointer.	
    

    Safe Object Initialization for Null Value

    The nullptr can be used for setting a pointer to null without causing any error or any garbage value. Here is an example to assign a null value to represent an empty linked list −

    #include <iostream>usingnamespace std;structNode{int data;
    	Node *next;};intmain(){
    	Node *head =nullptr;// Empty linked listif(head ==nullptr)
    		cout <<"Linked list is empty."<< endl;return0;}

    The output of the above code is given below −

    Linked list is empty.
    

    Function Overloading Resolution

    The nullptr is also used to resolve the ambiguity in function overloading. Here is an example.

    #include <iostream>usingnamespace std;voidshow(int n){
       cout <<"Integer called."<< endl;}voidshow(int*p){
       cout <<"Pointer called."<< endl;}intmain(){show(nullptr);// Calls pointerreturn0;}

    The output of the above code is given below −

    Pointer called.
    

    Conclusion

    In this chapter, we have understood that the nullptr in C++ is used when we need a null pointer. Before C++11, NULL was used, but it had various problems which is addressed by the nullptr. We have also discussed various use cases of nullptr with examples.

  • Lambda Expression in C++

    Lambda Expression

    A lambda expression in C++11 allows the user to define an anonymous function (a function without any name) inline, which captures variables from the surrounding scope. This makes them a powerful feature for various use cases, like callbacks, sortingfunctional programming, etc.

    Syntax

    Here is the syntax of lambda expression in C++:

    [capture](parameters)-> return_type 
    { 
        function_body 
    }

    Where,

    • capture specifies which variables from the outer scope are captured. It captures variables by value, by reference, or by both methods.
    • parameters are the input parameters for lambda.
    • return_type defines the return type of the lambda function. If the return type needs to be explicitly defined, it will follow this -> symbol.
    • body is the main body of the lambda, where function logic is written.

    Example of Lambda Expression

    In the following example, a lambda expression is used to add two numbers and return the result:

    #include <iostream>intmain(){// Define a lambda expression to add two numbersauto add =[](int a,int b){return a + b;};// Call the lambda expressionint result =add(5,3);
    
        std::cout <<"The sum of 5 and 3 is: "<< result << std::endl;return0;}

    Output

    The sum of 5 and 3 is: 8

    Capturing Variables in Lambda Expression

    Capturing variables in lambda expressions allows lambda to access variables from its surrounding scope. By a capture clause, a lambda can capture variables from its surrounding scope and allow it to use those variables inside the lambda body.

    Types of Variable Capture:

    1. Capture by value ([x])

    It captures the variables by values, which means lambda gets a copy of the variables and further cannot modify the original variable outside the lambda.

    [x](parameters)-> return_type { body }

    2. Capture by reference ([&x])

    It captures the variables by reference, which means here the lambda can access and modify the original variables.

    [&x](parameters)-> return_type { body }

    3. Capture Specific Variables ([x, &y])

    This allows you to mix capture types in the same lambda. Here, the user can specify which variables to capture by value or reference.

    [x,&y](parameters)-> return_type { body }

    4. Captures all variables by value ([=])

    It capturesallvariables in the surrounding scope by value.

    [=](parameters)-> return_type { body }

    5. Captures all variables by reference ([&])

    It captures all variables in the surrounding scope by reference.

    [&](parameters)-> return_type { body }

    Capture this by reference ([this])

    It captures this pointer (a reference to the current object) in a lambda expression. It is useful when the user needs to access member variables or functions from within a lambda in a class method.

    6. Capture by Mixed Modes

    • [=, &x] ,It captures all variables by value and x variable by reference.
    • [&, x] ,It captures all variables by reference and x by value.
    • [=, this] ,It captures this pointer by value and all other variables by value.

    Return Types in Lambda Expressions

    In C++, lambda expressions return the value just like regular functions, and its return type can be automatically deduced by the compiler or explicitly specified by the programmer.

    1. Automatic Return Type Deduction

    In this, the compiler deduces the return type based on the return expression inside the lambda.

    a) Implicit Return Type

    In this, the return type is based on the return expression, which means users don’t need to explicitly specify the return type; it will automatically be inferred from the type of the expression.

    [capture](parameters){return expression;}

    b) Returning References

    It returns references to variables or values; for this, make sure that the referenced variable stays in scope for the lifetime of the lambda.

    [capture](parameters)-> type&{return reference;}

    c) Returning Pointers

    A lambda can also return a pointer to a variable or dynamically allocated memory.

    [capture](parameters)-> type*{return pointer;}

    d) Type Deduction with auto

    Here, you can also use an auto keyword for the return type, and the compiler will deduce the correct return value type based on an expression.

    [capture](parameters)->auto{return value;}

    2. Explicit Return Type

    In this, if the user wants to specify lambda’s return type explicitly, then use -> return_type syntax. This is useful when working with any complex types and when the return type isn’t obvious.

    [capture](parameters)-> return_type {return expression;}

    Example

    #include <iostream>usingnamespace std;intmain(){int x =5;int y =10;auto my_lambda =[=,&x]()->int{
            cout <<"Inside lambda:"<< endl;// can't modify 'y' as it's captured by value// Modifying 'x' as it's captured by reference
            x +=10;
            cout <<"Captured 'x' by reference inside lambda: "<< x << endl;// Captured 'y' by value, so it can't be modified here// simple operation with 'y' and a local valueint sum = y +5;
            cout <<"Captured 'y' by value inside lambda: "<< y << endl;
            cout <<"Sum of 'y' and 5 inside lambda: "<< sum << endl;return sum;};// Call the lambdaint result =my_lambda();
        cout <<"Result returned from lambda: "<< result << endl;
        cout <<"Value of 'x' outside lambda after modification: "<< x << endl;
        cout <<"Value of 'y' outside lambda (no modification): "<< y << endl;return0;}

    When the above code is compiled and executed, it produces the following result −

    Inside lambda:
    Captured 'x' by reference inside lambda: 15
    Captured 'y' by value inside lambda: 10
    Sum of 'y' and 5 inside lambda: 15
    Result returned from lambda: 15
    Value of 'x' outside lambda after modification: 15
    Value of 'y' outside lambda (no modification): 10

    Recursive Lambdas

    In C++, recursive lambda is the lambda function that calls itself over again and again during its execution until it reaches its base case. As lambda by default cannot call themselves directly, because they don’t have a name. So for this, we can make lambda recursive by using a function pointer or std::function.

    Example

    #include <iostream>#include <functional> // for std::functionusingnamespace std;intmain(){// Defining the recursive lambda using std::function
        std::function<int(int)> factorial =[&](int n)->int{if(n <=1)return1;// Base casereturn n *factorial(n -1);// Recursive call};
        cout <<"Factorial of 5: "<<factorial(5)<< endl;}

    When the above code is compiled and executed, it produces the following result −

    Factorial of 5: 120
  • Advanced C++ Concepts

    C++ is a one of the foundation languages of modern programming. It has evolved out of the basic C into a very powerful tool in modern programming. The versions of C++ started with C++ 98, and are now upto C++ 20. After the update of C++ 11, all modern updates are known collectively as modern C++. These new models have vast and new features, making the language more user- friendly and better feature-equipped. Some of these new concepts were already part of other new languages like EthereumRubyPython, and Javascript, and with the introduction of these concepts in C++, programming has become more efficient today.

    Here is a list of different Advanced C++ topics we are going to understand in detail −

    With the version of C++ 20, other features are also available, which are a slightly more advanced and would be covered in the later parts of this post. The features mentioned above are far advanced concepts as well, but the explanation provided in this post shall be adequate for readers to deep dive into the MODERN C++ LANGUAGE.

    RAII (Resource Aquisition is Initialization)

    RAII

    Resource Acquisition is Initialization, often referred to by its acronym RAII, is a C++ technique which is used for memory management. Although it’s association with C++ is typically why it is studied, the scope of RAII extends beyond the barriers of language restrictions.

    To simply put up a definition, RAII means assigning memory to an object in form of a constructor, and then releasing the assigned memory using a destructor. Hence, it forms a part of OOP concepts, which was covered in the past topics.

    Now, you must be curious to know what problems does RAII actually solve? RAII works in many ways, some of which are −

    Some of these topics have already been discussed in the previous parts of this section, and some new concepts are discussed in the later parts of this post.

    Now, what is actually a resource in programming, particularly in terms of OOPS?

    A resource is an entity that can be required during the compilation or execution of a program or a sequence of programs. Examples of resources are StackHeapMemoryFilesSockets (in socket programming), Locks and Semaphores, etc. These resources are crucial for the smooth working of a program. These are acquired by the program through requests, like mutex() method calls for a mutex lock to be acquired.

    In classical programming using C, we use concepts of new() and delete() to create entities and then deallocate memory. This traditional concept, while still acceptable in OOP languages like C++, is however, discouraged. In C++, the concept of RAII makes it easy for allocation and deallocation of resources within a scope.

    The tenure of a new quantity is the tenure of the object, and while a constructor can create and assign memory to an object, a destructor can be used to simply release the memory after completion automatically. This makes C++ a very efficient and user-friendly language. Lets understand this with a simple example.

    Example

    #include <bits/stdc++.h>usingnamespace std;
    
    mutex m;voidbad(){
       m.lock();// acquire the mutexf();// if f() throws an exception, the mutex is never releasedif(!everything_ok())return;// early return, the mutex is never released
       m.unlock();// if bad() reaches this statement, the mutex is released}voidgood(){
       lock_guard<mutex>lk(m);// RAII class: mutex acquisition is initializationf();// if f() throws an exception, the mutex is releasedif(!everything_ok())return;// early return, the mutex is released}intmain(){good();bad();return0;}

    Wild Pointers in C++

    A pointer is called a wild pointer if it points randomly to any address in the memory. This happens when the pointer is declared in the program, but it is not initialized to point to an address value. Wild pointers are different from normal pointers i.e. they also store the memory addresses but point the unallocated memory or data value which has been deallocated.

    These pointers can cause memory leak, a topic that will be discussed in the later parts of this article.

    Example

    #include <bits/stdc++.h>usingnamespace std;intmain(){int*ptr;//this pointer has been declared but not initialized//hence, it is a wild pointer
       cout<<*ptr<<endl;int a=11;
       ptr=&a;
       cout<<*ptr<<endl<<ptr<<endl;//once a value is declared, it becomes a normal pointer*ptr=10;
       cout<<*ptr<<endl<<ptr;return0;}

    Output

    -660944088
    11
    0x7ffcfb77825c
    10
    0x7ffcfb77825c
    

    Null Pointers in C++

    In earlier versions of C++, the NULL would be defined as a void element which points to no memory. The conversion of NULL to int or similar data types was allowed, but in case of overloading of functions, the NULL pointer throws error.

    Since the emergence of C++ 11, the NULL was redefined to nullptr, which is a special data type that can only be used as a pointer to point to an address that is not available in the memory.

    Hence, it can act as a pointer to any location on redefining the pointer variable. Unlike NULL, it is not implicitly convertible or comparable to integral types, like int or char. Hence, it solves the problem of NULL invariably.

    On a side note, comparison between null pointers is possible in the newer version of C++, and hence it can be comprehended that pointers are comparable to bool data type.

    Example

    #include <bits/stdc++.h>usingnamespace std;intmain(){//int ptr=nullptr;//this throws compiler error as it is not comparable to int//run the above line for illustrationint*ptr=nullptr;if(ptr==nullptr) cout<<"true";else cout<<"false";return0;}

    Output

    true
    

    Memory Leakage in C++

    Memory leakage is a major problem in many computing devices, as the stack and heap memory available with the compiler in a program is limited and very costly. Memory leakage occurs when new objects are declared, used and not cleared out of the memory. This can happen if programmers forget to use the delete operation, or use it incorrectly.

    There are huge disadvantages with memory leakage, as the space is exponentially increasing with each incoming process request, and new processes have to be allocated new memory spaces instead of clearing unrequired memory.

    The given program illustrates how memory leak occurs in a program using C++.

    Example

    #include <bits/stdc++.h>usingnamespace std;voidleak_func(){int* p =newint(10);//using new() to declare a new object//no delete() operationreturn;}intmain(){leak_func();return0;}

    This can be avoided by deallocating the memory that was allocated in the first place to the new() object. The following program illustrates how memory leakage can be avoided.

    Example

    #include <bits/stdc++.h>usingnamespace std;voidleak_func(){int* p =newint(10);//using new() to declare a new objectdelete(p);return;}intmain(){leak_func();return0;}

    Smart Pointers in C++

    With the introduction of RAII and OOP concepts in C++, wrapper classes have also been introduced in C++. One of these wrapper classes is the Smart Pointer, which help to make sure there are no instances of memory leaks and errors.

    Example

    #include <bits/stdc++.h>usingnamespace std;intmain(){//int ptr=nullptr;//this throws compiler error as it is not comparable to intint*ptr=nullptr;if(ptr==nullptr) cout<<"true";else cout<<"false";return0;}

    Output

    true
    

    Lambda Expression in C++

    Since C++ 11, the use of lambda expression has been allowed in C++ to resolve inline functions which are used for small lines of code without the need to give the function a name and a scope.

    Syntax

    [ capture clause ](parameters)->return-type{   
       definition of method   
    }

    Here, the return type is resolved by the compiler itself, and there is no need to specify the return type of the function. However, in case of complex statements, the return type is specified for the compiler to run properly.

    External variables can be captured in the following ways −

    • Capture by reference
    • Capture by value
    • Capture by both (mixed capture)

    Syntax used for capturing variables is given as −

    • [&] : capture all external variables by reference
    • [=] : capture all external variables by value
    • [a, &b] : capture a by value and b by reference

    Example

    #include <bits/stdc++.h>usingnamespace std;voidprintvector(vector<int>&v){// lambda expression to print vectorfor_each(v.begin(), v.end(),[](int i){
          std::cout << i <<" ";});
       cout << endl;}intmain(){
       vector<int> v;
       v.push_back(10);
    
       v.push_back(11);
    
       v.push_back(12);printvector(v);return0;}

    Output

    10 11 12 
  • C++ Concurrency

    Concurrency refers to the ability of a system which allows one to manage multiple tasks or processes at any given time and allow them to progress without waiting for each other to complete. Tasks in concurrent systems may overlap in execution, which ultimately helps improve efficiency and resource utilization, especially in environments such as operating systems, databases, and web servers.

    Concurrency in C++

    In C++, concurrency helps developers create applications that can perform multiple operations and helps in improving their efficiency and responsiveness. Concurrency can occur in various ways, like through multi-threading, asynchronous programming, or distributed systems.

    Concurrency vs Parallelism

    Concurrency is the ability to manage different tasks or processors in an overlapping manner, meaning that tasks can be started, executed, and completed at different times. This means the tasks may not run simultaneously but their execution can overlap in time, making efficient use of available resources.

    Whereas, Parallelism is a subcategory of concurrency where tasks are actually executed concurrently on different processors or cores in order to improve performance.

    Concurrency deals with structure and task management, while parallelism focuses on simultaneous execution to speed up computation.

    Threads

    A thread represents the smallest unit of execution within a process, which allows multiple tasks to run independently and concurrently. The <thread>library is used to create and manage threads. Threads run in parallel and share the same memory space.

    Example

    Heres a simple example of threads in C++ −

    #include <iostream>#include <thread>voidhello(){
       std::cout <<"Hello Learner!"<< std::endl;}intmain(){
       std::thread t(hello);
       t.join();// Wait for the thread to finishreturn0;}

    Output

    Hello Learner!
    

    Thread Synchronization in C++

    Thread synchronization in C++ is a mechanism that manages the access of shared resources by multiple threads to prevent data races, inconsistencies, and undefined behavior. It makes sure that only one thread can access a resource at a time or that specific operations are performed in a specific order, especially when multiple threads are executing concurrently.

    Key Methods of Thread Synchronization in C++

    The following are some of the key methods of thread synchronization in C++ −

    Mutex (<mutex> Library)

    A mutex (mutual exclusion) is a locking mechanism that limits access to shared resources so that only one thread can access it at a time. If one thread locks a mutex, other threads trying to lock the same mutex are blocked until the mutex is unlocked.

    std::lock_guard and std::unique_lock

    std::lock_guard is a basic automatic lock manager, which locks a mutex when created and unlocks it when it goes out of scope.

    std::unique_lock is more flexible and allows manual unlocking and re-locking.

    Condition Variables (<condition_variable> Library)

    It enables threads to wait until certain conditions are met, which facilitates communication between threads.

    std::condition_variable is typically used with std::unique_lock<std::mutex> and provides wait(), notify_one(), and notify_all() functions for blocking and resuming threads based on specific conditions.

    Atomic Variables (<atomic> Library)

    Atomic operations are another way to ensure thread safety without using mutexes.

    An atomic variable guarantees that any read-modify-write operations are done without interference from other threads, which can be useful for simple data types like integers or booleans.

    Atomic operations include fetch_add, load, store, and compare_exchange.

    Semaphore

    A semaphore is a synchronization primitive that manages access to shared resources in a concurrent system, like a multithreaded or multiprocess environment. A semaphore is essentially an integer value that controls access to resources. It operates on two main operations −

    • Wait (P or acquire): Decreases the semaphore value.
    • Signal (V or release): Increases the semaphore value.

    Asynchronous Execution in C++

    In C++, std::future and std::promise are mechanisms which are used for asynchronous programming that help manage data or result in communication between threads, allowing one thread to provide a result (via std::promise) and another to retrieve it (via std::future). These are part of the C++11 standard and are found in the <future> header.

    Key Components for Asynchronous Programming

    • std::future − It represents a future result of an asynchronous operation. A thread can retrieve the result from a future once it’s available, and if the result isn’t ready, the std::future::get() − Function will block until the value is computed.
    • std::promise − It is used to set a value or an exception that can later be retrieved via a std::future.
    • std::async − It is used to launch a task asynchronously. It returns a std::future that can be used to obtain the result of the task once it’s completed.
  • C++ Socket Programming

    C++ socket programming is the way to establish communication between two sockets on the network using C++. In this tutorial, we will learn all about socket programming using different types of sockets in C++.

    What are Sockets?

    Sockets act as the contact points for network data exchange, it’s like endpoints for sending and receiving data across a network. They allow applications to communicate with one another using protocols such as TCP (Transmission Control Protocol) and UDP (User Datagram Protocol). They are the backbone of most internet communication as it enables us from web browsing to real-time chatting.

    There are two types of sockets:

    • Stream Sockets (TCP):
      It provides reliable, connection-oriented communication where data is sent in a continuous stream making sure that packets arrive in order and without errors.
    • Datagram Sockets (UDP):
      It provides connectionless communication. Where It transfers data in packets independently, but does not guarantee an order or delivery making it sent in a quick and less reliable way.

    Socket Programming in C++

    Socket programming in C++ is a powerful approach to creating network applications that allow communication between devices over a network using the socket API. This process involves establishing connections between a client and a server, which enables data exchange through protocols like TCP or UDP.

    C++ Server-Side Socket (Listening for Connections)

    The following methods are used for handling server-side communication:

    1. socket()

    The socket() is a system call in network programming that creates a new TCP socket in C++ that is defined inside the <sys/socket.h> header file.

    Syntax

    int sockfd =socket(AF_INET, SOCK_STREAM,0);

    Where,

    • int sockfd declares an integer variable that will store the socket file descriptor.
    • AF_INET indicates the socket will use the IPv4 address family.
    • SOCK_STREAM specifies that the socket will use TCP (a stream-oriented protocol) and,
    • 0 lets the system choose the default protocol for the specified address family and socket type (which is TCP in this case).

    2. bind()

    The bind() method is associated with a socket, with a specific local address and port number which allows the socket to listen for incoming connection on that address.

    Syntax

    bind(sockfd,(structsockaddr*)&address,sizeof(address));

    Where,

    • sockfd is the file descriptor that represents the socket in your program and is used to perform various socket operations
    • (struct sockaddr)&address casts the address structure to a generic pointer type for the bind function.
    • sizeof(address) specifies the size of the address structure to inform the system how much data to expect.

    3. listen()

    The listen() function marks the socket as a passive socket which prepares a socket to accept incoming connection requests (for servers).

    Syntax

    listen(sockfd,10);

    Where,

    • sockfd is the file descriptor that represents the socket in your program and is used to perform various socket operations
    • 10 is the backlog parameter, which specifies the maximum number of pending connections that can be queued while the server is busy.

    4. accept()

    The accept() function accepts a new connection from a client (for servers). It extracts the first connection request on the queue of pending connections and creates a new socket for that connection.

    Syntax

    int clientSocket =accept(sockfd,(structsockaddr*)&clientAddress,&clientLen);

    Where,

    • sockfd: It’s the socket’s file descriptor where it is used to perform various socket operations.
    • (struct sockaddr)&address: This is a type cast that converts the pointer type of clientAddress to a pointer of type struct sockaddr*.
    • &clientLen: It is a pointer to a variable that holds the size of the clientAddress.

    C++ Client-Side Socket (Connecting to a Server)

    The following methods are used for client-side communication:

    1. connect()

    This function is a system call that attempts to establish a connection to a specified server (for clients) using the socket.

    Syntax

    connect(sockfd,(structsockaddr*)&serverAddress,sizeof(serverAddress));

    Where,

    • sockfd is the file descriptor that represents the socket in your program and is used to perform various socket operations.
    • (struct sockaddr*)&serverAddress casts serverAddress to a struct sockaddr* pointer which enables compatibility with functions that require a generic socket address type.
    • sizeof(serverAddress) specifies the size of the serverAddress

    2. send()

    The send() function is a system call in socket programming which sends data to a connected socket.

    Syntax

    send(sockfd,"Hello",strlen("Hello"),0);

    Where,

    • sockfd is the file descriptor that represents the socket in your program and is used to perform various socket operations.
    • strlen(“Hello”) function returns the length of the string “Hello” (5 bytes), showing how many bytes of data to send.
    • 0 lets the system choose the default protocol for the specified address family and socket type (which is TCP in this case).

    3. recv()

    The recv() function is a system call that is used to receive data from a connected socket which allows the client or server to read incoming messages.

    Syntax

    recv(sockfd, buffer,sizeof(buffer),0);

    Where,

    • sockfd is the file descriptor that represents the socket in your program and is used to perform various socket operations.
    • buffer is a pointer to the memory location where the received data will be stored. This buffer should be large enough to hold the incoming data.
    • sizeof(buffer) specifies the maximum number of bytes to read from the socket, which is typically the size of the buffer.

    Closing the Client Socket

    The close() method closes an open socket.

    Syntax

    close(sockfd);

    Where,

    • close function is a system call that closes the file descriptor associated with the socket.

    Required Header Files for Socket Programming

    When programming with sockets in C or C++, specific header files must be included for the necessary declarations.

    For Linux/Unix Systems

    • <sys/socket.h>
    •  <netinet/in.h>
    •  <arpa/inet.h>
    •  <unistd.h>
    •  <string.h>
    •  <errno.h>

    For Windows Systems

    • <winsock2.h>
    • <ws2tcpip.h>
    • <windows.h>

    C++ Example of Socket Programming

    Here’s a simple Example to illustrate a TCP server and client in C++:

    TCP Server Code

    #include <netinet/in.h>#include <sys/socket.h>#include <unistd.h>#include <cstring>#include <iostream>#define PORT 8080intmain(){int server_fd, new_socket;structsockaddr_in address;int opt =1;int addrlen =sizeof(address);char buffer[1024]={0};// Create socket
      server_fd =socket(AF_INET, SOCK_STREAM,0);if(server_fd ==0){perror("socket failed");exit(EXIT_FAILURE);}// Attach socket to the portsetsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR,&opt,sizeof(opt));
      address.sin_family = AF_INET;
      address.sin_addr.s_addr = INADDR_ANY;
      address.sin_port =htons(PORT);// Bindif(bind(server_fd,(structsockaddr*)&address,sizeof(address))<0){perror("bind failed");exit(EXIT_FAILURE);}// Listenif(listen(server_fd,3)<0){perror("listen");exit(EXIT_FAILURE);}// Accept a connection
      new_socket =accept(server_fd,(structsockaddr*)&address,(socklen_t *)&addrlen);if(new_socket <0){perror("accept");exit(EXIT_FAILURE);}// Read dataread(new_socket, buffer,1024);
      std::cout <<"Message from client: "<< buffer << std::endl;// Close socketclose(new_socket);close(server_fd);return0;}

    TCP Client Code

    #include <arpa/inet.h>#include <netinet/in.h>#include <sys/socket.h>#include <unistd.h>#include <cstring>#include <iostream>#define PORT 8080intmain(){int sock =0;structsockaddr_in serv_addr;constchar*hello ="Hello from client";// Create socket
      sock =socket(AF_INET, SOCK_STREAM,0);if(sock <0){
        std::cerr <<"Socket creation error"<< std::endl;return-1;}
    
      serv_addr.sin_family = AF_INET;
      serv_addr.sin_port =htons(PORT);// Convert IPv4 and IPv6 addresses from text to binaryif(inet_pton(AF_INET,"127.0.0.1",&serv_addr.sin_addr)<=0){
        std::cerr <<"Invalid address/ Address not supported"<< std::endl;return-1;}// Connect to serverif(connect(sock,(structsockaddr*)&serv_addr,sizeof(serv_addr))<0){
        std::cerr <<"Connection Failed"<< std::endl;return-1;}// Send datasend(sock, hello,strlen(hello),0);
      std::cout <<"Message sent"<< std::endl;// Close socketclose(sock);return0;}

    Steps to Compile and Run

    The following are the steps to compiler and run client socket program:

    To compiler both server and client code files:

    g++-o server server.cpp
    g++-o client client.cpp
    

    To run the Server:

    ./server
    

    To run the Client (in another terminal):

    ./client
    

    Best Practices

    • Error Handling: Always check the return values of socket functions to handle errors properly.
    • Blocking vs Non-blocking: By default, sockets operate in blocking mode. So, consider using non-blocking sockets or multiplexing (like select or poll) for handling multiple connections.
    • Cross-platform Issues: This example is for Unix/Linux. For Windows, you’ll need to include <winsock2.h> and initialize Winsock with WSAStartup().

    Real-world Applications

    There are various applications of sockets in real-life uses and tools etc, here’s mentioned a few of them.

    These examples demonstrate how to use sockets for different applications:

    • Echo Server: A straightforward server that echoes received messages.
    • Chat Application: A multi-threaded server that allows multiple clients to chat.
    • FTP Client/Server: A simple implementation for transferring files over a network.
    • Web Server: Sockets handle HTTP requests and responses for serving web content.
    • Online Multiplayer Games: Sockets enable real-time communication between players and game servers.
    • Remote Access Tools: Sockets provide secure connections for remote administration of servers.
    • VoIP Applications: Sockets transmit audio and video data in real time for communication.
    • Streaming Services: Sockets deliver continuous audio and video content to users.
    • IoT Devices: Sockets facilitate communication between smart devices and servers.
    • Real-Time Collaboration Tools: Sockets allow instant sharing of edits and messages among users.
    • Data Synchronization Services: Sockets manage file uploads and downloads between devices and servers.
    • Weather Monitoring Systems: Sockets send real-time weather data to central servers for analysis.
    • Payment Processing Systems: Sockets securely transmit transaction data between clients and banks.
    • Chatbots: Sockets enable immediate messaging and responses in conversational interfaces.
  • C++ Web Programming

    What is CGI?

    • The Common Gateway Interface, or CGI, is a set of standards that define how information is exchanged between the web server and a custom script.
    • The CGI specs are currently maintained by the NCSA and NCSA defines CGI is as follows −
    • The Common Gateway Interface, or CGI, is a standard for external gateway programs to interface with information servers such as HTTP servers.
    • The current version is CGI/1.1 and CGI/1.2 is under progress.

    Web Browsing

    To understand the concept of CGI, let’s see what happens when we click a hyperlink to browse a particular web page or URL.

    • Your browser contacts the HTTP web server and demand for the URL ie. filename.
    • Web Server will parse the URL and will look for the filename. If it finds requested file then web server sends that file back to the browser otherwise sends an error message indicating that you have requested a wrong file.
    • Web browser takes response from web server and displays either the received file or error message based on the received response.

    However, it is possible to set up the HTTP server in such a way that whenever a file in a certain directory is requested, that file is not sent back; instead it is executed as a program, and produced output from the program is sent back to your browser to display.

    The Common Gateway Interface (CGI) is a standard protocol for enabling applications (called CGI programs or CGI scripts) to interact with Web servers and with clients. These CGI programs can be a written in Python, PERL, Shell, C or C++ etc.

    CGI Architecture Diagram

    The following simple program shows a simple architecture of CGI −

    CGI Architecture

    Web Server Configuration

    Before you proceed with CGI Programming, make sure that your Web Server supports CGI and it is configured to handle CGI Programs. All the CGI Programs to be executed by the HTTP server are kept in a pre-configured directory. This directory is called CGI directory and by convention it is named as /var/www/cgi-bin. By convention CGI files will have extension as .cgi, though they are C++ executable.

    By default, Apache Web Server is configured to run CGI programs in /var/www/cgi-bin. If you want to specify any other directory to run your CGI scripts, you can modify the following section in the httpd.conf file −

    <Directory "/var/www/cgi-bin">
       AllowOverride None
       Options ExecCGI
       Order allow,deny
       Allow from all
    </Directory><Directory "/var/www/cgi-bin">
       Options All
    </Directory>

    Here, I assume that you have Web Server up and running successfully and you are able to run any other CGI program like Perl or Shell etc.

    First CGI Program

    Consider the following C++ Program content −

    #include <iostream>usingnamespace std;intmain(){
       cout <<"Content-type:text/html\r\n\r\n";
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>Hello World - First CGI Program</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";
       cout <<"<h2>Hello World! This is my first CGI program</h2>\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    Compile above code and name the executable as cplusplus.cgi. This file is being kept in /var/www/cgi-bin directory and it has following content. Before running your CGI program make sure you have change mode of file using chmod 755 cplusplus.cgi UNIX command to make file executable.

    My First CGI program

    The above C++ program is a simple program which is writing its output on STDOUT file i.e. screen. There is one important and extra feature available which is first line printing Content-type:text/html\r\n\r\n. This line is sent back to the browser and specify the content type to be displayed on the browser screen. Now you must have understood the basic concept of CGI and you can write many complicated CGI programs using Python. A C++ CGI program can interact with any other external system, such as RDBMS, to exchange information.

    HTTP Header

    The line Content-type:text/html\r\n\r\n is a part of HTTP header, which is sent to the browser to understand the content. All the HTTP header will be in the following form −

    HTTP Field Name: Field Content
     
    For Example
    Content-type: text/html\r\n\r\n
    

    There are few other important HTTP headers, which you will use frequently in your CGI Programming.

    Sr.NoHeader & Description
    1Content-type:A MIME string defining the format of the file being returned. Example is Content-type:text/html.
    2Expires: DateThe date the information becomes invalid. This should be used by the browser to decide when a page needs to be refreshed. A valid date string should be in the format 01 Jan 1998 12:00:00 GMT.
    3Location: URLThe URL that should be returned instead of the URL requested. You can use this filed to redirect a request to any file.
    4Last-modified: DateThe date of last modification of the resource.
    5Content-length: NThe length, in bytes, of the data being returned. The browser uses this value to report the estimated download time for a file.
    6Set-Cookie: StringSet the cookie passed through the string.

    CGI Environment Variables

    All the CGI program will have access to the following environment variables. These variables play an important role while writing any CGI program.

    Sr.NoVariable Name & Description
    1CONTENT_TYPEThe data type of the content, used when the client is sending attached content to the server. For example file upload etc.
    2CONTENT_LENGTHThe length of the query information that is available only for POST requests.
    3HTTP_COOKIEReturns the set cookies in the form of key & value pair.
    4HTTP_USER_AGENTThe User-Agent request-header field contains information about the user agent originating the request. It is a name of the web browser.
    5PATH_INFOThe path for the CGI script.
    6QUERY_STRINGThe URL-encoded information that is sent with GET method request.
    7REMOTE_ADDRThe IP address of the remote host making the request. This can be useful for logging or for authentication purpose.
    8REMOTE_HOSTThe fully qualified name of the host making the request. If this information is not available then REMOTE_ADDR can be used to get IR address.
    9REQUEST_METHODThe method used to make the request. The most common methods are GET and POST.
    10SCRIPT_FILENAMEThe full path to the CGI script.
    11SCRIPT_NAMEThe name of the CGI script.
    12SERVER_NAMEThe server’s hostname or IP Address.
    13SERVER_SOFTWAREThe name and version of the software the server is running.

    Here is small CGI program to list out all the CGI variables.

    #include <iostream>#include <stdlib.h>usingnamespace std;const string ENV[24]={"COMSPEC","DOCUMENT_ROOT","GATEWAY_INTERFACE","HTTP_ACCEPT","HTTP_ACCEPT_ENCODING","HTTP_ACCEPT_LANGUAGE","HTTP_CONNECTION","HTTP_HOST","HTTP_USER_AGENT","PATH","QUERY_STRING","REMOTE_ADDR","REMOTE_PORT","REQUEST_METHOD","REQUEST_URI","SCRIPT_FILENAME","SCRIPT_NAME","SERVER_ADDR","SERVER_ADMIN","SERVER_NAME","SERVER_PORT","SERVER_PROTOCOL","SERVER_SIGNATURE","SERVER_SOFTWARE"};intmain(){
       cout <<"Content-type:text/html\r\n\r\n";
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>CGI Environment Variables</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";
       cout <<"<table border = \"0\" cellspacing = \"2\">";for(int i =0; i <24; i++){
          cout <<"<tr><td>"<< ENV[ i ]<<"</td><td>";// attempt to retrieve value of environment variablechar*value =getenv( ENV[ i ].c_str());if( value !=0){
             cout << value;}else{
             cout <<"Environment variable does not exist.";}
          cout <<"</td></tr>\n";}
       
       cout <<"</table><\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    C++ CGI Library

    For real examples, you would need to do many operations by your CGI program. There is a CGI library written for C++ program which you can download from ftp://ftp.gnu.org/gnu/cgicc/ and follow the steps to install the library −

    $tar xzf cgicc-X.X.X.tar.gz 
    $cd cgicc-X.X.X/ 
    $./configure --prefix=/usr 
    $make
    $make install
    

    You can check related documentation available at C++ CGI Lib Documentation.

    GET and POST Methods

    You must have come across many situations when you need to pass some information from your browser to web server and ultimately to your CGI Program. Most frequently browser uses two methods to pass this information to web server. These methods are GET Method and POST Method.

    Passing Information Using GET Method

    The GET method sends the encoded user information appended to the page request. The page and the encoded information are separated by the ? character as follows −

    http://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2
    

    The GET method is the default method to pass information from browser to web server and it produces a long string that appears in your browser’s Location:box. Never use the GET method if you have password or other sensitive information to pass to the server. The GET method has size limitation and you can pass upto 1024 characters in a request string.

    When using GET method, information is passed using QUERY_STRING http header and will be accessible in your CGI Program through QUERY_STRING environment variable.

    You can pass information by simply concatenating key and value pairs alongwith any URL or you can use HTML <FORM> tags to pass information using GET method.

    Simple URL Example: Get Method

    Here is a simple URL which will pass two values to hello_get.py program using GET method./cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

    Below is a program to generate cpp_get.cgi CGI program to handle input given by web browser. We are going to use C++ CGI library which makes it very easy to access passed information −

    #include <iostream>#include <vector>  #include <string>  #include <stdio.h>  #include <stdlib.h> #include <cgicc/CgiDefs.h> #include <cgicc/Cgicc.h> #include <cgicc/HTTPHTMLHeader.h> #include <cgicc/HTMLClasses.h>  usingnamespace std;usingnamespace cgicc;intmain(){
       Cgicc formData;
       
       cout <<"Content-type:text/html\r\n\r\n";
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>Using GET and POST Methods</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";
    
       form_iterator fi = formData.getElement("first_name");if(!fi->isEmpty()&& fi !=(*formData).end()){  
          cout <<"First name: "<<**fi << endl;}else{
          cout <<"No text entered for first name"<< endl;}
       
       cout <<"<br/>\n";
       fi = formData.getElement("last_name");if(!fi->isEmpty()&&fi !=(*formData).end()){  
          cout <<"Last name: "<<**fi << endl;}else{
          cout <<"No text entered for last name"<< endl;}
       
       cout <<"<br/>\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    Now, compile the above program as follows −

    $g++-o cpp_get.cgi cpp_get.cpp -lcgicc
    

    Generate cpp_get.cgi and put it in your CGI directory and try to access using following link −/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

    This would generate following result −

    First name: ZARA 
    Last name: ALI 
    

    Simple FORM Example: GET Method

    Here is a simple example which passes two values using HTML FORM and submit button. We are going to use same CGI script cpp_get.cgi to handle this input.

    <form action ="/cgi-bin/cpp_get.cgi" method ="get">
       First Name:<input type ="text" name ="first_name"><br />
     
       Last Name:<input type ="text" name ="last_name"/><input type ="submit" value ="Submit"/></form>

    Here is the actual output of the above form. You enter First and Last Name and then click submit button to see the result.First Name:  Last Name:  

    Passing Information Using POST Method

    A generally more reliable method of passing information to a CGI program is the POST method. This packages the information in exactly the same way as GET methods, but instead of sending it as a text string after a ? in the URL it sends it as a separate message. This message comes into the CGI script in the form of the standard input.

    The same cpp_get.cgi program will handle POST method as well. Let us take same example as above, which passes two values using HTML FORM and submit button but this time with POST method as follows −

    <form action ="/cgi-bin/cpp_get.cgi" method ="post">
       First Name:<input type ="text" name ="first_name"><br />
       Last Name:<input type ="text" name ="last_name"/><input type ="submit" value ="Submit"/></form>

    Here is the actual output of the above form. You enter First and Last Name and then click submit button to see the result.First Name:  Last Name:  

    Passing Checkbox Data to CGI Program

    Checkboxes are used when more than one option is required to be selected.

    Here is example HTML code for a form with two checkboxes −

    <form action ="/cgi-bin/cpp_checkbox.cgi" method ="POST" target ="_blank"><input type ="checkbox" name ="maths" value ="on"/> Maths
       <input type ="checkbox" name ="physics" value ="on"/> Physics
       <input type ="submit" value ="Select Subject"/></form>

    The result of this code is the following form − Maths  Physics 

    Below is C++ program, which will generate cpp_checkbox.cgi script to handle input given by web browser through checkbox button.

    #include <iostream>#include <vector>  #include <string>  #include <stdio.h>  #include <stdlib.h> #include <cgicc/CgiDefs.h> #include <cgicc/Cgicc.h> #include <cgicc/HTTPHTMLHeader.h> #include <cgicc/HTMLClasses.h> usingnamespace std;usingnamespace cgicc;intmain(){
       Cgicc formData;bool maths_flag, physics_flag;
    
       cout <<"Content-type:text/html\r\n\r\n";
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>Checkbox Data to CGI</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";
    
       maths_flag = formData.queryCheckbox("maths");if( maths_flag ){  
          cout <<"Maths Flag: ON "<< endl;}else{
          cout <<"Maths Flag: OFF "<< endl;}
       cout <<"<br/>\n";
    
       physics_flag = formData.queryCheckbox("physics");if( physics_flag ){  
          cout <<"Physics Flag: ON "<< endl;}else{
          cout <<"Physics Flag: OFF "<< endl;}
       
       cout <<"<br/>\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    Passing Radio Button Data to CGI Program

    Radio Buttons are used when only one option is required to be selected.

    Here is example HTML code for a form with two radio button −

    <form action ="/cgi-bin/cpp_radiobutton.cgi" method ="post" target ="_blank"><input type ="radio" name ="subject" value ="maths" checked ="checked"/> Maths 
       <input type ="radio" name ="subject" value ="physics"/> Physics
       <input type ="submit" value ="Select Subject"/></form>

    The result of this code is the following form − Maths  Physics 

    Below is C++ program, which will generate cpp_radiobutton.cgi script to handle input given by web browser through radio buttons.

    #include <iostream>#include <vector>  #include <string>  #include <stdio.h>  #include <stdlib.h> #include <cgicc/CgiDefs.h> #include <cgicc/Cgicc.h> #include <cgicc/HTTPHTMLHeader.h> #include <cgicc/HTMLClasses.h> usingnamespace std;usingnamespace cgicc;intmain(){
       Cgicc formData;
      
       cout <<"Content-type:text/html\r\n\r\n";
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>Radio Button Data to CGI</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";
    
       form_iterator fi = formData.getElement("subject");if(!fi->isEmpty()&& fi !=(*formData).end()){  
          cout <<"Radio box selected: "<<**fi << endl;}
      
       cout <<"<br/>\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    Passing Text Area Data to CGI Program

    TEXTAREA element is used when multiline text has to be passed to the CGI Program.

    Here is example HTML code for a form with a TEXTAREA box −

    <form action ="/cgi-bin/cpp_textarea.cgi" method ="post" target ="_blank"><textarea name ="textcontent" cols ="40" rows ="4">
          Type your text here...</textarea><input type ="submit" value ="Submit"/></form>

    The result of this code is the following form −

    Below is C++ program, which will generate cpp_textarea.cgi script to handle input given by web browser through text area.

    #include <iostream>#include <vector>  #include <string>  #include <stdio.h>  #include <stdlib.h> #include <cgicc/CgiDefs.h> #include <cgicc/Cgicc.h> #include <cgicc/HTTPHTMLHeader.h> #include <cgicc/HTMLClasses.h> usingnamespace std;usingnamespace cgicc;intmain(){
       Cgicc formData;
      
       cout <<"Content-type:text/html\r\n\r\n";
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>Text Area Data to CGI</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";
    
       form_iterator fi = formData.getElement("textcontent");if(!fi->isEmpty()&& fi !=(*formData).end()){  
          cout <<"Text Content: "<<**fi << endl;}else{
          cout <<"No text entered"<< endl;}
      
       cout <<"<br/>\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    Passing Drop down Box Data to CGI Program

    Drop down Box is used when we have many options available but only one or two will be selected.

    Here is example HTML code for a form with one drop down box −

    <form action ="/cgi-bin/cpp_dropdown.cgi" method ="post" target ="_blank"><select name ="dropdown"><option value ="Maths" selected>Maths</option><option value ="Physics">Physics</option></select><input type ="submit" value ="Submit"/></form>

    The result of this code is the following form − Maths Physics  

    Below is C++ program, which will generate cpp_dropdown.cgi script to handle input given by web browser through drop down box.

    #include <iostream>#include <vector>  #include <string>  #include <stdio.h>  #include <stdlib.h> #include <cgicc/CgiDefs.h> #include <cgicc/Cgicc.h> #include <cgicc/HTTPHTMLHeader.h> #include <cgicc/HTMLClasses.h> usingnamespace std;usingnamespace cgicc;intmain(){
       Cgicc formData;
      
       cout <<"Content-type:text/html\r\n\r\n";
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>Drop Down Box Data to CGI</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";
    
       form_iterator fi = formData.getElement("dropdown");if(!fi->isEmpty()&& fi !=(*formData).end()){  
          cout <<"Value Selected: "<<**fi << endl;}
      
       cout <<"<br/>\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    Using Cookies in CGI

    HTTP protocol is a stateless protocol. But for a commercial website it is required to maintain session information among different pages. For example one user registration ends after completing many pages. But how to maintain user’s session information across all the web pages.

    In many situations, using cookies is the most efficient method of remembering and tracking preferences, purchases, commissions, and other information required for better visitor experience or site statistics.

    How It Works

    Your server sends some data to the visitor’s browser in the form of a cookie. The browser may accept the cookie. If it does, it is stored as a plain text record on the visitor’s hard drive. Now, when the visitor arrives at another page on your site, the cookie is available for retrieval. Once retrieved, your server knows/remembers what was stored.

    Cookies are a plain text data record of 5 variable-length fields −

    • Expires − This shows date the cookie will expire. If this is blank, the cookie will expire when the visitor quits the browser.
    • Domain − This shows domain name of your site.
    • Path − This shows path to the directory or web page that set the cookie. This may be blank if you want to retrieve the cookie from any directory or page.
    • Secure − If this field contains the word “secure” then the cookie may only be retrieved with a secure server. If this field is blank, no such restriction exists.
    • Name = Value − Cookies are set and retrieved in the form of key and value pairs.

    Setting up Cookies

    It is very easy to send cookies to browser. These cookies will be sent along with HTTP Header before the Content-type filed. Assuming you want to set UserID and Password as cookies. So cookies setting will be done as follows

    #include <iostream>usingnamespace std;intmain(){
       cout <<"Set-Cookie:UserID = XYZ;\r\n";
       cout <<"Set-Cookie:Password = XYZ123;\r\n";
       cout <<"Set-Cookie:Domain = www.tutorialspoint.com;\r\n";
       cout <<"Set-Cookie:Path = /perl;\n";
       cout <<"Content-type:text/html\r\n\r\n";
    
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>Cookies in CGI</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";
    
       cout <<"Setting cookies"<< endl;  
      
       cout <<"<br/>\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    From this example, you must have understood how to set cookies. We use Set-Cookie HTTP header to set cookies.

    Here, it is optional to set cookies attributes like Expires, Domain, and Path. It is notable that cookies are set before sending magic line “Content-type:text/html\r\n\r\n.

    Compile above program to produce setcookies.cgi, and try to set cookies using following link. It will set four cookies at your computer −

    /cgi-bin/setcookies.cgi

    Retrieving Cookies

    It is easy to retrieve all the set cookies. Cookies are stored in CGI environment variable HTTP_COOKIE and they will have following form.

    key1 = value1; key2 = value2; key3 = value3....
    

    Here is an example of how to retrieve cookies.

    #include <iostream>#include <vector>  #include <string>  #include <stdio.h>  #include <stdlib.h> #include <cgicc/CgiDefs.h> #include <cgicc/Cgicc.h> #include <cgicc/HTTPHTMLHeader.h> #include <cgicc/HTMLClasses.h>usingnamespace std;usingnamespace cgicc;intmain(){
       Cgicc cgi;
       const_cookie_iterator cci;
    
       cout <<"Content-type:text/html\r\n\r\n";
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>Cookies in CGI</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";
       cout <<"<table border = \"0\" cellspacing = \"2\">";// get environment variablesconst CgiEnvironment& env = cgi.getEnvironment();for( cci = env.getCookieList().begin();
       cci != env.getCookieList().end();++cci ){
          cout <<"<tr><td>"<< cci->getName()<<"</td><td>";
          cout << cci->getValue();                                 
          cout <<"</td></tr>\n";}
       
       cout <<"</table><\n";
       cout <<"<br/>\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    Now, compile above program to produce getcookies.cgi, and try to get a list of all the cookies available at your computer −

    /cgi-bin/getcookies.cgi

    This will produce a list of all the four cookies set in previous section and all other cookies set in your computer −

    UserID XYZ 
    Password XYZ123 
    Domain www.tutorialspoint.com 
    Path /perl 
    

    File Upload Example

    To upload a file the HTML form must have the enctype attribute set to multipart/form-data. The input tag with the file type will create a “Browse” button.

    <html><body><form enctype ="multipart/form-data" action ="/cgi-bin/cpp_uploadfile.cgi"
             method ="post"><p>File:<input type ="file" name ="userfile"/></p><p><input type ="submit" value ="Upload"/></p></form></body></html>

    The result of this code is the following form −

    File: 

    Note − Above example has been disabled intentionally to stop people uploading files on our server. But you can try above code with your server.

    Here is the script cpp_uploadfile.cpp to handle file upload −

    #include <iostream>#include <vector>  #include <string>  #include <stdio.h>  #include <stdlib.h> #include <cgicc/CgiDefs.h> #include <cgicc/Cgicc.h> #include <cgicc/HTTPHTMLHeader.h> #include <cgicc/HTMLClasses.h>usingnamespace std;usingnamespace cgicc;intmain(){
       Cgicc cgi;
    
       cout <<"Content-type:text/html\r\n\r\n";
       cout <<"<html>\n";
       cout <<"<head>\n";
       cout <<"<title>File Upload in CGI</title>\n";
       cout <<"</head>\n";
       cout <<"<body>\n";// get list of files to be uploaded
       const_file_iterator file = cgi.getFile("userfile");if(file != cgi.getFiles().end()){// send data type at cout.
          cout <<HTTPContentHeader(file->getDataType());// write content at cout.
          file->writeToStream(cout);}
       cout <<"<File uploaded successfully>\n";
       cout <<"</body>\n";
       cout <<"</html>\n";return0;}

    The above example is for writing content at cout stream but you can open your file stream and save the content of uploaded file in a file at desired location.

    Hope you have enjoyed this tutorial. If yes, please send us your feedback.

  • C++ Multithreading

    Multithreading is a specialized form of multitasking and a multitasking is the feature that allows your computer to run two or more programs concurrently. In general, there are two types of multitasking: process-based and thread-based.

    Process-based multitasking handles the concurrent execution of programs. Thread-based multitasking deals with the concurrent execution of pieces of the same program.

    A multithreaded program contains two or more parts that can run concurrently. Each part of such a program is called a thread, and each thread defines a separate path of execution.

    Before C++ 11, there is no built-in support for multithreaded applications. Instead, it relies entirely upon the operating system to provide this feature.

    This tutorial assumes that you are working on Linux OS and we are going to write multi-threaded C++ program using POSIX. POSIX Threads, or Pthreads provides API which are available on many Unix-like POSIX systems such as FreeBSD, NetBSD, GNU/Linux, Mac OS X and Solaris.

    Creating Threads

    The following routine is used to create a POSIX thread −

    #include <pthread.h>pthread_create(thread, attr, start_routine, arg)

    Here, pthread_create creates a new thread and makes it executable. This routine can be called any number of times from anywhere within your code. Here is the description of the parameters −

    Sr.NoParameter & Description
    1threadAn opaque, unique identifier for the new thread returned by the subroutine.
    2attrAn opaque attribute object that may be used to set thread attributes. You can specify a thread attributes object, or NULL for the default values.
    3start_routineThe C++ routine that the thread will execute once it is created.
    4argA single argument that may be passed to start_routine. It must be passed by reference as a pointer cast of type void. NULL may be used if no argument is to be passed.

    The maximum number of threads that may be created by a process is implementation dependent. Once created, threads are peers, and may create other threads. There is no implied hierarchy or dependency between threads.

    Terminating Threads

    There is following routine which we use to terminate a POSIX thread −

    #include <pthread.h>pthread_exit(status)

    Here pthread_exit is used to explicitly exit a thread. Typically, the pthread_exit() routine is called after a thread has completed its work and is no longer required to exist.

    If main() finishes before the threads it has created, and exits with pthread_exit(), the other threads will continue to execute. Otherwise, they will be automatically terminated when main() finishes.

    Example

    This simple example code creates 5 threads with the pthread_create() routine. Each thread prints a “Hello World!” message, and then terminates with a call to pthread_exit().

    #include <iostream>#include <cstdlib>#include <pthread.h>usingnamespace std;#define NUM_THREADS 5void*PrintHello(void*threadid){long tid;
       tid =(long)threadid;
       cout <<"Hello World! Thread ID, "<< tid << endl;pthread_exit(NULL);}intmain(){
       pthread_t threads[NUM_THREADS];int rc;int i;for( i =0; i < NUM_THREADS; i++){
          cout <<"main() : creating thread, "<< i << endl;
          rc =pthread_create(&threads[i],NULL, PrintHello,(void*)i);if(rc){
             cout <<"Error:unable to create thread,"<< rc << endl;exit(-1);}}pthread_exit(NULL);}

    Compile the following program using -lpthread library as follows −

    $gcc test.cpp -lpthread
    

    Now, execute your program which gives the following output −

    main() : creating thread, 0
    main() : creating thread, 1
    main() : creating thread, 2
    main() : creating thread, 3
    main() : creating thread, 4
    Hello World! Thread ID, 0
    Hello World! Thread ID, 1
    Hello World! Thread ID, 2
    Hello World! Thread ID, 3
    Hello World! Thread ID, 4
    

    Passing Arguments to Threads

    This example shows how to pass multiple arguments via a structure. You can pass any data type in a thread callback because it points to void as explained in the following example −

    #include <iostream>#include <cstdlib>#include <pthread.h>usingnamespace std;#define NUM_THREADS 5structthread_data{int  thread_id;char*message;};void*PrintHello(void*threadarg){structthread_data*my_data;
       my_data =(structthread_data*) threadarg;
    
       cout <<"Thread ID : "<< my_data->thread_id ;
       cout <<" Message : "<< my_data->message << endl;pthread_exit(NULL);}intmain(){
       pthread_t threads[NUM_THREADS];structthread_data td[NUM_THREADS];int rc;int i;for( i =0; i < NUM_THREADS; i++){
          cout <<"main() : creating thread, "<< i << endl;
          td[i].thread_id = i;
          td[i].message ="This is message";
          rc =pthread_create(&threads[i],NULL, PrintHello,(void*)&td[i]);if(rc){
             cout <<"Error:unable to create thread,"<< rc << endl;exit(-1);}}pthread_exit(NULL);}

    When the above code is compiled and executed, it produces the following result −

    main() : creating thread, 0
    main() : creating thread, 1
    main() : creating thread, 2
    main() : creating thread, 3
    main() : creating thread, 4
    Thread ID : 3 Message : This is message
    Thread ID : 2 Message : This is message
    Thread ID : 0 Message : This is message
    Thread ID : 1 Message : This is message
    Thread ID : 4 Message : This is message
    

    Joining and Detaching Threads

    There are following two routines which we can use to join or detach threads −

    pthread_join (threadid, status) 
    pthread_detach (threadid) 
    

    The pthread_join() subroutine blocks the calling thread until the specified ‘threadid’ thread terminates. When a thread is created, one of its attributes defines whether it is joinable or detached. Only threads that are created as joinable can be joined. If a thread is created as detached, it can never be joined.

    This example demonstrates how to wait for thread completions by using the Pthread join routine.

    #include <iostream>#include <cstdlib>#include <pthread.h>#include <unistd.h>usingnamespace std;#define NUM_THREADS 5void*wait(void*t){int i;long tid;
    
       tid =(long)t;sleep(1);
       cout <<"Sleeping in thread "<< endl;
       cout <<"Thread with id : "<< tid <<"  ...exiting "<< endl;pthread_exit(NULL);}intmain(){int rc;int i;
       pthread_t threads[NUM_THREADS];
       pthread_attr_t attr;void*status;// Initialize and set thread joinablepthread_attr_init(&attr);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);for( i =0; i < NUM_THREADS; i++){
          cout <<"main() : creating thread, "<< i << endl;
          rc =pthread_create(&threads[i],&attr, wait,(void*)i );if(rc){
             cout <<"Error:unable to create thread,"<< rc << endl;exit(-1);}}// free attribute and wait for the other threadspthread_attr_destroy(&attr);for( i =0; i < NUM_THREADS; i++){
          rc =pthread_join(threads[i],&status);if(rc){
             cout <<"Error:unable to join,"<< rc << endl;exit(-1);}
          cout <<"Main: completed thread id :"<< i ;
          cout <<"  exiting with status :"<< status << endl;}
    
       cout <<"Main: program exiting."<< endl;pthread_exit(NULL);}

    When the above code is compiled and executed, it produces the following result −

    main() : creating thread, 0
    main() : creating thread, 1
    main() : creating thread, 2
    main() : creating thread, 3
    main() : creating thread, 4
    Sleeping in thread
    Thread with id : 0 .... exiting
    Sleeping in thread
    Thread with id : 1 .... exiting
    Sleeping in thread
    Thread with id : 2 .... exiting
    Sleeping in thread
    Thread with id : 3 .... exiting
    Sleeping in thread
    Thread with id : 4 .... exiting
    Main: completed thread id :0  exiting with status :0
    Main: completed thread id :1  exiting with status :0
    Main: completed thread id :2  exiting with status :0
    Main: completed thread id :3  exiting with status :0
    Main: completed thread id :4  exiting with status :0
    Main: program exiting.
  • C++ Signal Handling

    Signals are the interrupts delivered to a process by the operating system which can terminate a program prematurely. You can generate interrupts by pressing Ctrl+C on a UNIX, LINUX, Mac OS X or Windows system.

    There are signals which can not be caught by the program but there is a following list of signals which you can catch in your program and can take appropriate actions based on the signal. These signals are defined in C++ header file <csignal>.

    Sr.NoSignal & Description
    1SIGABRTAbnormal termination of the program, such as a call to abort.
    2SIGFPEAn erroneous arithmetic operation, such as a divide by zero or an operation resulting in overflow.
    3SIGILLDetection of an illegal instruction.
    4SIGINTReceipt of an interactive attention signal.
    5SIGSEGVAn invalid access to storage.
    6SIGTERMA termination request sent to the program.

    The signal() Function

    C++ signal-handling library provides function signal to trap unexpected events. Following is the syntax of the signal() function −

    void(*signal(int sig,void(*func)(int)))(int);

    Keeping it simple, this function receives two arguments: first argument as an integer which represents signal number and second argument as a pointer to the signal-handling function.

    Let us write a simple C++ program where we will catch SIGINT signal using signal() function. Whatever signal you want to catch in your program, you must register that signal using signal function and associate it with a signal handler. Examine the following example −

    #include <iostream>#include <csignal>usingnamespace std;voidsignalHandler(int signum ){
       cout <<"Interrupt signal ("<< signum <<") received.\n";// cleanup and close up stuff here  // terminate program  exit(signum);}intmain(){// register signal SIGINT and signal handler  signal(SIGINT, signalHandler);while(1){
          cout <<"Going to sleep...."<< endl;sleep(1);}return0;}

    When the above code is compiled and executed, it produces the following result −

    Going to sleep....
    Going to sleep....
    Going to sleep....
    

    Now, press Ctrl+c to interrupt the program and you will see that your program will catch the signal and would come out by printing something as follows −

    Going to sleep....
    Going to sleep....
    Going to sleep....
    Interrupt signal (2) received.
    

    The raise() Function

    You can generate signals by function raise(), which takes an integer signal number as an argument and has the following syntax.

    intraise(signal sig);

    Here, sig is the signal number to send any of the signals: SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGHUP. Following is the example where we raise a signal internally using raise() function as follows −

    #include <iostream>#include <csignal>usingnamespace std;voidsignalHandler(int signum ){
       cout <<"Interrupt signal ("<< signum <<") received.\n";// cleanup and close up stuff here  // terminate program  exit(signum);}intmain(){int i =0;// register signal SIGINT and signal handler  signal(SIGINT, signalHandler);while(++i){
          cout <<"Going to sleep...."<< endl;if( i ==3){raise( SIGINT);}sleep(1);}return0;}

    When the above code is compiled and executed, it produces the following result and would come out automatically −

    Going to sleep....
    Going to sleep....
    Going to sleep....
    Interrupt signal (2) received.