Thread: Circular buffer - console crashing

  1. #1
    Registered User
    Join Date
    Dec 2015
    Posts
    92

    Circular buffer - console crashing

    Hello guys my console crashes when I try to run this code

    Code:
    #include "stdafx.h"
    #include <stdio.h>
    #include <iostream>
    
    
    #define MAX_ITEMS 10
    
    
    
    struct CircularQueue
    {
        int first;
        int last;
        int validItems;
        int data[MAX_ITEMS];
    };
    
    
    void initiliazeQueue(CircularQueue* queue)
    {
        queue->validItems = 0;
        queue->first = 0;
        queue->last = 0;
    
    
        for (int i = 0; i < MAX_ITEMS; i++)
        {
            queue->data[i] = 0;
        }
    
    
    }
    
    
    int isEmpty(CircularQueue* queue)
    {
        if (queue->validItems == 0)
            return 1;
        else
            return 0;
    }
    
    
    int enqueue(CircularQueue* queue, int itemValue)
    {
        if (queue->validItems >= MAX_ITEMS)
        {
            std::cout << "The queue is full\n";
            std::cout << "\You cannot add items\n";
            return -1;
        }
        else
        {
            queue->validItems++;
            queue->data[queue->last] = itemValue;
            queue->last = (queue->last + 1) % MAX_ITEMS;
            return 0;
        }
    }
    
    
    int dequeue(CircularQueue* queue, int* itemValue)
    {
        if (isEmpty(queue))
        {
            printf("is empty\n");
            return -1;
        }
        else
        {
            *itemValue = queue->data[queue->first];
            queue->first = (queue->first + 1) % MAX_ITEMS;
            queue->validItems--;
            return 0;
        }
    }
    
    
    void printQueue(CircularQueue* queue)
    {
        int aux, aux1;
        aux = queue->first;
        aux1 = queue->validItems;
        while (aux1>0)
        {
            printf("Element #%d = %d\n", aux, queue->data[aux]);
            aux = (aux + 1) % MAX_ITEMS;
            aux1--;
        }
        return;
    }
    
    
    using namespace std;
    
    
    int main()
    {
        CircularQueue* circularQueue = new CircularQueue;
        initiliazeQueue(circularQueue);
        int* buffer = NULL;
    
    
        if (isEmpty(circularQueue))
            std::cout << "Queue is empty" << endl;
         
        enqueue(circularQueue, 5);
        enqueue(circularQueue, 12);
        printQueue(circularQueue);
    
    
        if (isEmpty(circularQueue) == -1)
            std::cout << "Queue is empty" << endl;
    
    
        
    
        dequeue(circularQueue, buffer);
        std::cout << "After dequeue" << endl;
        printQueue(circularQueue);
    
    
        return 0;
    }
    This line is doing problems, so I tried to change it
    Code:
        
    
        dequeue(circularQueue, buffer);
    to something like this

    Code:
        
    
        dequeue(circularQueue, &buffer);
    But the file didn't copile then.

  2. #2
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    You misunderstood how dequeue() is used here. You should pass it a pointer to a valid integer variable. NULL is what caused the crashing. Either dynamically allocate it with malloc/calloc or( better in my opinion ) change it to a local variable and pass its pointer.
    Devoted my life to programming...

  3. #3
    Registered User
    Join Date
    Dec 2015
    Posts
    92
    Quote Originally Posted by GReaper View Post
    You misunderstood how dequeue() is used here. You should pass it a pointer to a valid integer variable. NULL is what caused the crashing. Either dynamically allocate it with malloc/calloc or( better in my opinion ) change it to a local variable and pass its pointer.
    Changed it to
    Code:
    int* buffer = (int*)malloc(sizeof(int));
    and it worked, thank you.

    Haven't used C/C++ in a while and I jumped back from Java, I want to refresh my knownledge and clarify some things, so
    Code:
    dequeue(&circularQueue, &buffer);
    why this doesn't seem to work in C/C++, I am passing a memory location to the function, isn't that the same like
    Code:
    dequeue(circularQueue, buffer);
    since both circularQueue and buffer store allocated memory address and pointers are just variables that store memory address?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Or even just
    int buffer;
    dequeue(&circularQueue, &buffer);


    > why this doesn't seem to work in C/C++
    Not thinking about C and C++ as being interchangeable would be a good start.
    C is one language, C++ is another language, C/C++ is a mashup train-wreck waiting to happen.

    If you're coming from Java, you should really have begun with
    class CircularQueue
    and made all your functions members of the class.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Dec 2015
    Posts
    92
    Quote Originally Posted by Salem View Post
    Or even just
    int buffer;
    dequeue(&circularQueue, &buffer);


    > why this doesn't seem to work in C/C++
    Not thinking about C and C++ as being interchangeable would be a good start.
    C is one language, C++ is another language, C/C++ is a mashup train-wreck waiting to happen.


    If you're coming from Java, you should really have begun with
    class CircularQueue
    and made all your functions members of the class.

    First language I learnt was C, and after that it was C++.
    I use Java most on my current job.


    What I am trying to implement is SerialCommunication class for sending/receiving data via UART with a microcontroller using interrupts.


    When I make sure everything works I will write a class for it.


    Here is a new code, since I got it working I changed BUFFER_SIZE to power of 2 and using AND operation instead of modulus operation.


    Added some new functions.


    Code:
    // Circular Buffer.cpp : Defines the entry point for the console application.
    //
    #include "stdafx.h"
    #include <stdio.h>
    #include <iostream>
    
    
    
    
    using namespace std;
    
    
    
    
    #define BUFFER_SIZE 8
    #define BUFFER_MASK (BUFFER_SIZE - 1)
    
    
    
    
    struct CircularQueue
    {
        int first;
        int last;
        int validItems;
        int data[BUFFER_SIZE];
    };
    
    
    
    
    
    
    
    
    void initiliazeQueue(CircularQueue* queue)
    {
        queue->validItems = 0;
        queue->first = 0;
        queue->last = 0;
    
    
    
    
        for (int i = 0; i < BUFFER_SIZE; i++)
        {
            queue->data[i] = NULL;
        }
    
    
    
    
    }
    
    
    
    
    
    
    
    
    int isEmpty(CircularQueue* queue)
    {
        if (queue->validItems == 0)
            return 1;
        else
            return 0;
    }
    
    
    
    
    int getFreeElemNum(CircularQueue* queue)
    {
        return ((BUFFER_SIZE - queue->first + queue->last) & BUFFER_MASK);
    }
    
    
    
    
    bool availabile(CircularQueue* queue)
    {
        if (((BUFFER_SIZE - queue->first + queue->last) & BUFFER_MASK))
        {
            return true;
        }
        return false;
    }
    int getOccupiedElemNum(CircularQueue* queue)
    {
        return (BUFFER_SIZE - ((BUFFER_SIZE - queue->first + queue->last) & BUFFER_MASK));
    }
    
    
    
    
    int enqueue(CircularQueue* queue, int itemValue)
    {
        if (queue->validItems >= BUFFER_SIZE)
        {
            std::cout << "The queue is full\n";
            std::cout << "You cannot add items\n";
            return -1;
        }
    
    
    
    
        else
        {
            queue->validItems++;
            queue->data[queue->last] = itemValue;
            queue->last = (queue->last + 1) & BUFFER_MASK;
            return 0;
        }
    }
    
    
    
    
    
    
    
    
    int dequeue(CircularQueue* queue, int* itemValue)
    {
        if (isEmpty(queue))
        {
            printf("is empty\n");
            return 1;
        }
        else
        {
            *itemValue = queue->data[queue->first];
            queue->first = (queue->first + 1) & BUFFER_MASK;
            queue->validItems--;
            return 0;
        }
    }
    
    
    
    
    
    
    
    
    void printQueue(CircularQueue* queue)
    {
        int aux, aux1;
        aux = queue->first;
        aux1 = queue->validItems;
        while (aux1>0)
        {
            printf("Element #%d = %d\n", aux, queue->data[aux]);
            aux = (aux + 1) & BUFFER_MASK;
            aux1--;
        }
        return;
    }
    
    
    
    
    /*
    void receive(CircularQueue* queue, int buffer[BUFFER_SIZE])
    {
        int* tempElement = (int*)malloc(sizeof(int));
        
        int tempBuffer[BUFFER_SIZE];
        int i = 0;
        do {
            if (dequeue(queue, tempElement))
                break;
            tempBuffer[i++] = *tempElement;
        } while (true);
    
    
    
    
        memcpy(buffer, tempBuffer, sizeof(tempBuffer));
        
    }
    */
    int* receive(CircularQueue* queue)
    {
        int* tempElement = (int*)malloc(sizeof(int));
        const int TEMP_BUFFER_SIZE = getOccupiedElemNum(queue);
        int* tempBuffer = (int*)malloc(TEMP_BUFFER_SIZE * sizeof(int));
        int i = 0;
        do {
            if (dequeue(queue, tempElement))
                break;
            tempBuffer[i++] = *tempElement;
        } while (true);
    
    
    
    
        delete(tempElement);
    
    
    
    
        return tempBuffer;
    }
    
    
    
    
    void print(int* buffer)
    {
        for (int i = 0; *buffer != NULL; ++i)
            printf("Buffer[%d]: %d\n", i, *buffer++);
    }
    
    
    
    
    int main()
    {
        CircularQueue* circularQueue = new CircularQueue;
        int* buffer = (int*)malloc(sizeof(int) * BUFFER_SIZE);
        //int buffer[BUFFER_SIZE];
    
    
    
    
        initiliazeQueue(circularQueue);
    
    
    
    
        if (isEmpty(circularQueue))
            std::cout << "Queue is empty" << endl;
    
    
    
    
        enqueue(circularQueue, 1);
        enqueue(circularQueue, 2);
        enqueue(circularQueue, 3);
        enqueue(circularQueue, 4);
        enqueue(circularQueue, 5);
        enqueue(circularQueue, 6);
        enqueue(circularQueue, 7);
        enqueue(circularQueue, 8);
        enqueue(circularQueue, 9);
        
        printQueue(circularQueue);
    
    
    
    
    
    
    
    
        if (isEmpty(circularQueue) == -1)
            std::cout << "Queue is empty" << endl;
    
    
    
    
        dequeue(circularQueue, buffer);
        std::cout << "After dequeue" << endl;
        printQueue(circularQueue);
        //receive(circularQueue, buffer);
        buffer = receive(circularQueue);
        std::cout << "After calling print function" << endl;
        print(buffer);
        
        delete(circularQueue);
        
        return 0;
    }

    Code compiled without errors but console crashes, so I guess I messed something up while using pointers.


    in the function receive


    Code:
    int* receive(CircularQueue* queue)
    {
        int* tempElement = (int*)malloc(sizeof(int));
        const int TEMP_BUFFER_SIZE = getOccupiedElemNum(queue);
        int* tempBuffer = (int*)malloc(TEMP_BUFFER_SIZE * sizeof(int));
        int i = 0;
        do {
            if (dequeue(queue, tempElement))
                break;
            tempBuffer[i++] = *tempElement;
        } while (true);
    
    
    
    
        delete(tempElement);
    
    
    
    
        return tempBuffer;
    }

    I tried to calculate number of occupied elements in queue with


    Code:
    const int TEMP_BUFFER_SIZE = getOccupiedElemNum(queue);

    So I dont return unwanted values from a function.


    So for example if i have in my queue[8] = {1 ,2 ,3 ,4 ,5 ,6, 7, 0}


    I want to print only from 1 - 7 I don't want to print 0.
    And this function wont take care of it


    Code:
    
    void print(int* buffer)
    {
        for (int i = 0; *buffer != NULL; ++i)
            printf("Buffer[%d]: %d\n", i, *buffer++);
    }

    but I don't know any better solution of this so I need some help.
    I wouldn't bother you guys with it but since it's a weekend I can't ask any of colleuges who are experts in C/C++.
    Attached Images Attached Images Circular buffer - console crashing-capture-jpg 
    Last edited by High Voltage; 02-25-2017 at 07:07 AM.

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Code:
    delete(tempElement);
    You should only delete what was created by a new!
    You should free what was created by malloc.

    Tim S.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  7. #7
    Registered User
    Join Date
    Dec 2015
    Posts
    92
    Quote Originally Posted by stahta01 View Post
    Code:
    delete(tempElement);
    You should only delete what was created by a new!
    You should free what was created by malloc.

    Tim S.
    Thank you I figured out what was causing the problem.
    Should I use calloc over malloc when creating buffer since it is array?

  8. #8
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,738
    Quote Originally Posted by High Voltage View Post
    Should I use calloc over malloc when creating buffer since it is array?
    If you want to be sure that your array doesn't contain any "random" values, yes calloc() is what you can use to initialize all the bytes to zero.
    Devoted my life to programming...

  9. #9
    Registered User
    Join Date
    Dec 2015
    Posts
    92
    Quote Originally Posted by GReaper View Post
    If you want to be sure that your array doesn't contain any "random" values, yes calloc() is what you can use to initialize all the bytes to zero.
    Alright I got another question. Calling by reference in C++ is same like calling by pointers in C if I remember right?


    Code:
    bool isEmpty(CircularQueue& queue)
    {
        if (((BUFFER_SIZE - queue.head + queue.tail) & BUFFER_MASK))
            return false;
        else
            return true;
    }
    
    
    bool isFull(CircularQueue& queue)
    {
        if (BUFFER_SIZE - ((BUFFER_SIZE - queue.head + queue.tail) & BUFFER_MASK))
            return false;
        else
            return true;
    }
    
    
    
    
    bool dequeue(CircularQueue& queue)
    {
        if (isEmpty(queue))
        {
            return false;
        }
        queue.head = (queue.front + 1) & BUFFER_MASK;
        return true;
    }
    
    
    bool enqueue(CircularQueue& queue, const ElementType& element)
    {
        if (queueIsFull())
        {
            return false;
        }
        queue.buffer[queue.tail] = element;
        queue.tail = (queue.getTail + 1) & BUFFER_MASK;
        return true;
    }
    Do I have to allocate memory at heap to use call by reference
    Code:
    CircularQueue* queue = new (CircularQueue);
    I know this is also valid in C++
    Code:
    CircularQueue queue;
    I like the first one since it looks more like Java style, but on the other hand I have to use 'queue->method()' syntax instead of 'queue.method()'

    Also I hope my logic for isEmpty() and isFull() functions is valid

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Quote Originally Posted by GReaper View Post
    If you want to be sure that your array doesn't contain any "random" values, yes calloc() is what you can use to initialize all the bytes to zero.
    Not all data types are necessarily represented by all-bits-zero in memory.
    Question 7.31
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Quote Originally Posted by High Voltage View Post
    Alright I got another question. Calling by reference in C++ is same like calling by pointers in C if I remember right?
    No.
    difference between pointer and reference - Google Search
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 10-04-2015, 05:17 PM
  2. Circular Buffer using Virtual Memory
    By SMurf in forum Windows Programming
    Replies: 5
    Last Post: 03-26-2013, 07:05 PM
  3. Replies: 3
    Last Post: 11-11-2010, 12:05 PM
  4. Circular buffer - logic difficulty
    By erasm in forum C Programming
    Replies: 2
    Last Post: 10-05-2009, 01:08 PM
  5. Circular Buffer
    By parisframe in forum C Programming
    Replies: 11
    Last Post: 09-16-2009, 11:05 PM

Tags for this Thread