Program crash on deque from queue

-1

My first question asked here, so please excuse if I fail to include something...

I'm working on a homework project, which basically consists of creating a "Jukebox" (importing/exporting albums from txt files, creating and "playing" a playlist, etc.).

I've become stuck on one point: When "playing" the playlist, which consists of a self-made Queue, a copy of it is made from which songs are dequeued and printed out with a time delay. This appears to run fine on the first run through the program, but if the "play" option is chosen again (with the same playlist, created from a different menu option), it crashes before managing to print the first song. It also crashes if creating a new playlist, but then it manages to print some songs (seem to depend on the number of songs in the first/new playlists...) before crashing.

With printouts I've been able to track the crashing down to being on the "item = n->data" call in the deque function... but can't get my head around why this would crash.

Below is the code I think should be relevant... let me know if there are other parts that would help if I include.

Edit: The Debug Error shown on crash is: R6010 abort() has been called

The method to play from the playlist:

void Jukebox::playList()
{
    if(songList.getNodes() > 0) 
    {
        Queue tmpList(songList);
        Song tmpSong;
        while(tmpList.deque(tmpSong)) {
            clock_t temp;
            temp = clock () + 2 * CLOCKS_PER_SEC ;
            while (clock() < temp) {}
        }
    }
    else
        cout << "There are no songs in the playlist!" << endl;
}

Queue:

// Queue.h - Projekt-uppgift
//-----------------------------------------------------------------------------
#ifndef queue_h
#define queue_h
    #include "Song.h"
    using namespace std;
    typedef Song Item;
    class Node;
class Queue
{
    private:
        Node *first;
        Node *last;
        int nodes;

    public:
        Queue():first(nullptr),last(nullptr),nodes(0){};
        ~Queue();
        void enque(Item item);
        bool deque(Item &item);
        int getNodes() const { return nodes; }
        void empty();
};
#endif


// Queue.cpp - Projekt-uppgift
//-----------------------------------------------------------------------------
#include "queue.h"
using namespace std;

class Node
{
    public:
    Node *next;
    Item data;
    Node (Node *n, Item newData) : next(n), data(newData) {}
};

//------------------------------------------------------------------------------
// Funktionsdefinitioner för klassen Queue
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Destruktor
//------------------------------------------------------------------------------
Queue::~Queue()
{
    while(first!=0)
    {
        Node *tmp = first;
        first = first->next;
        delete tmp;
    }
}
//------------------------------------------------------------------------------
// Lägg till data sist i kön
//------------------------------------------------------------------------------
void Queue::enque(Item item)
{
    Node *pNew = new Node(0,item);
    if(getNodes() < 1)
        first = pNew;
    else
        last->next = pNew;
    last = pNew;
    nodes++;
}
//------------------------------------------------------------------------------
// Ta bort data först i kön
//------------------------------------------------------------------------------
bool Queue::deque(Item &item)
{
    if(getNodes() < 1)
        return false;
    //cout << "deque: test2" << endl;
    Node *n = first;
    //cout << "deque: test3" << endl;
    //cout << "item = " << item << endl;
    //cout << "first = " << first << endl;
    //cout << "n->data = " << n->data << endl;
    item = n->data;
    //cout << "deque: test4" << endl;
    first = first->next;
    //delete n;
    nodes--;
    if(getNodes() < 1)            // Kön BLEV tom
        last = nullptr;
    return true;
}
//------------------------------------------------------------------------------
// Töm kön
//------------------------------------------------------------------------------
void Queue::empty()
{
   while (getNodes() > 0)
   {
       Item item;
       deque(item);
   }
}
//------------------------------------------------------------------------------

Song:

// Song.h - Projekt-uppgift
//-----------------------------------------------------------------------------
#ifndef song_h
#define song_h
    #include "Time.h"
    #include <string>
    #include <iostream>
    using namespace std;
class Song
{
    private:
        string title;
        string artist;
        Time length;

    public:
        Song();
        Song(string pTitle, string pArtist, Time pLength);
        // Setfunktioner
        void setTitle(string pTitle);
        void setArtist(string pArtist);
        void setLength(Time pLength);
        // Getfunktioner
        string getTitle() const { return title;}
        string getArtist() const { return artist;}
        Time getLength() const { return length;}
};

ostream &operator<<(ostream &os, const Song &song);
istream &operator>>(istream &is, Song &song);

#endif


// Song.cpp - Projekt-uppgift
//-----------------------------------------------------------------------------
#include "Song.h"
#include "Constants.h"
#include <iostream>
//------------------------------------------------------------------------------
// Definiering av Songs medlemsfunktioner
//------------------------------------------------------------------------------
// Fövald konstruktor
//------------------------------------------------------------------------------
Song::Song()
{

}

//------------------------------------------------------------------------------
// Initieringskonstruktor
//------------------------------------------------------------------------------
Song::Song(string pTitle, string pArtist, Time pLength)
{
    title = pTitle;
    artist = pArtist;
    length = pLength;
}

//------------------------------------------------------------------------------
// Setfunktioner
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// setTitle
//   Ange titel
//------------------------------------------------------------------------------
void Song::setTitle(string pTitle)
{
    title = pTitle;
}
//------------------------------------------------------------------------------
// setArtist
//   Ange artist
//------------------------------------------------------------------------------
void Song::setArtist(string pArtist)
{
    artist = pArtist;
}
//------------------------------------------------------------------------------
// setTitle
//   Ange titel
//------------------------------------------------------------------------------
void Song::setLength(Time pLength)
{
    length = pLength;
}
//---------------------------------------------------------------------------
// Överlagring av utskriftsoperatorn
//---------------------------------------------------------------------------
ostream &operator<<(ostream &os, const Song &song)
{
    os << song.getTitle() << DELIM << song.getArtist() << DELIM << song.getLength();

    return os;
}
//---------------------------------------------------------------------------
// Överlagring av inmatningsoperatorn
//---------------------------------------------------------------------------
istream &operator>>(istream &is, Song &song)
{
    string tmpString;
    Time tmpLength;
    getline(is, tmpString, DELIM);
    song.setTitle(tmpString);
    getline(is, tmpString, DELIM);
    song.setArtist(tmpString);
    is >> tmpLength;
    is.get();
    song.setLength(tmpLength);
    return is;
}
//---------------------------------------------------------------------------

Album:

// Album.h - Projekt-uppgift
//-----------------------------------------------------------------------------
#ifndef album_h
#define album_h
    #include "Song.h"
    #include <string>
    #include <vector>
    #include <iostream>
    using namespace std;
class Album
{
    private:
        string name;
        vector<Song> songs;

    public:
        Album();
        Album(string pNameTitle, vector<Song> pSongs);
        // Setfunktioner
        void setName(string pName);
        // Getfunktioner
        string getName() const { return name;}
        vector<Song> getSongs() const { return songs;}
        int getNumberOfSongs() const { return songs.size();}
        Time getTotalTime() const;
        void addSong(Song pSong);

        bool operator<(const Album &album) const;
};

ostream &operator<<(ostream &os, const Album &album);
istream &operator>>(istream &is, Album &album);

#endif

// Album.cpp - Projekt-uppgift
//-----------------------------------------------------------------------------
#include "Album.h"
#include "Constants.h"
#include <iostream>
#include <string>
//------------------------------------------------------------------------------
// Definiering av Albums medlemsfunktioner
//------------------------------------------------------------------------------
// Fövald konstruktor
//------------------------------------------------------------------------------
Album::Album()
{

}

//------------------------------------------------------------------------------
// Initieringskonstruktor
//------------------------------------------------------------------------------
Album::Album(string pName, vector<Song> pSongs)
{
    name = pName;
    songs = pSongs;
}

//------------------------------------------------------------------------------
// Setfunktioner
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// setName
//   Ange namn
//------------------------------------------------------------------------------
void Album::setName(string pName)
{
    name = pName;
}
//------------------------------------------------------------------------------
// addSong
//   Lägg till song
//------------------------------------------------------------------------------
void Album::addSong(Song pSong)
{
    songs.push_back(pSong);
}
//------------------------------------------------------------------------------
// getTotalTime
//   Returnera total speltid
//------------------------------------------------------------------------------
Time Album::getTotalTime() const
{
    Time tTime(0,0,0);
    for(Song s : songs)
    {
        tTime = tTime + s.getLength();
    }
    return tTime;
}
//---------------------------------------------------------------------------
// Mindre än
//---------------------------------------------------------------------------
bool Album::operator<(const Album &album) const
{
    return getTotalTime() < album.getTotalTime();
}
//---------------------------------------------------------------------------
// Överlagring av utskriftsoperatorn
//---------------------------------------------------------------------------
ostream &operator<<(ostream &os, const Album &album)
{
    os << album.getName() << endl;
    os << album.getNumberOfSongs() << endl;
    for (size_t i = 0; i < album.getSongs().size(); i++)
        os << album.getSongs().at(i) << endl;

    return os;
}
//---------------------------------------------------------------------------
// Överlagring av inmatningsoperatorn
//---------------------------------------------------------------------------
istream &operator>>(istream &is, Album &album)
{
    string tmpString;
    int tmpNumberOfSongs;
    Song tmpSong;
    getline(is, tmpString);
    album.setName(tmpString);
    is >> tmpNumberOfSongs;
    is.get();
    for (int i = 0; i < tmpNumberOfSongs; i++)
    {
        is >> tmpSong;
        album.addSong(tmpSong);
    }
    return is;
}
//---------------------------------------------------------------------------

Time:

// Time.h - Projekt-uppgift
//-----------------------------------------------------------------------------
#ifndef time_h
#define time_h
    #include <iostream>
    using namespace std;
class Time
{
    private:
        int hours;
        int minutes;
        int seconds;

    public:
        Time();
        Time(int pHour, int pMinute, int pSecond);
        // Setfunktioner
        void setHour(int pHour);
        void setMinute(int pMinute);
        void setSecond(int pSecond);
        // Getfunktioner
        int getHour() const { return hours;}
        int getMinute() const { return minutes;}
        int getSecond() const { return seconds;}

        Time operator+(const Time &time) const;
        bool operator==(const Time &time) const;
        bool operator<(const Time &time) const;
};

ostream &operator<<(ostream &os, const Time &time);
istream &operator>>(istream &is, Time &Time);

#endif


// Time.cpp - Projekt-uppgift
//-----------------------------------------------------------------------------
#include "Time.h"
#include <iostream>
//------------------------------------------------------------------------------
// Definiering av Times medlemsfunktioner
//------------------------------------------------------------------------------
// Fövald konstruktor
//------------------------------------------------------------------------------
Time::Time()
{

}

//------------------------------------------------------------------------------
// Initieringskonstruktor
//------------------------------------------------------------------------------
Time::Time(int pHour, int pMinute, int pSecond)
{
    setHour(pHour);
    setMinute(pMinute);
    setSecond(pSecond);
}

//------------------------------------------------------------------------------
// Setfunktioner
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// setHour
//   Ange timme
//------------------------------------------------------------------------------
void Time::setHour(int pHour)
{
    if(pHour>-1)
        hours = pHour;
    else
        hours = 0;
}
//------------------------------------------------------------------------------
// setMinute
//   Ange minut
//------------------------------------------------------------------------------
void Time::setMinute(int pMinute)
{
    if(pMinute < 60 && pMinute > -1) {
        minutes = pMinute;
    }
    else
        minutes = 0;
}
//------------------------------------------------------------------------------
// setSecond
//   Ange sekund
//------------------------------------------------------------------------------
void Time::setSecond(int pSecond)
{
    if(pSecond < 60 && pSecond > -1) {
        seconds = pSecond;
    }
    else
        seconds = 0;
}
//---------------------------------------------------------------------------
// Överlagring av utskriftsoperatorn
//---------------------------------------------------------------------------
ostream &operator<<(ostream &os, const Time &time)
{
    os << time.getHour()*3600+time.getMinute()*60+time.getSecond();
    return os;
}
//---------------------------------------------------------------------------
// Överlagring av inmatningsoperatorn
//---------------------------------------------------------------------------
istream &operator>>(istream &is, Time &time)
{
    int tmp;
    is >> tmp;
    time.setSecond(tmp%60);
    time.setMinute((tmp/60)%60);
    time.setHour(tmp/3600);
    return is;
}
//---------------------------------------------------------------------------
// Likhet
//--------------------------------------------------------------------------
bool Time::operator==(const Time &time) const
{
    return hours == time.getHour() && minutes == time.getMinute() && seconds == time.getSecond();
}
//---------------------------------------------------------------------------
// Mindre än
//---------------------------------------------------------------------------
bool Time::operator<(const Time &time) const
{
    if(hours == time.getHour()) {
        if(minutes == time.getMinute()) {
            return seconds < time.getSecond();
        }
        else {
            return minutes < time.getMinute();
        }
    }
    else {
        return hours < time.getHour();
    }
}
//---------------------------------------------------------------------------
// Addition
//---------------------------------------------------------------------------
Time Time::operator+(const Time &time) const
{
    return Time(hours+time.getHour() + (minutes+time.getMinute() + (seconds+time.getSecond())/60)/60, (minutes+time.getMinute() + (seconds+time.getSecond())/60)%60, (seconds+time.getSecond())%60);
}
//---------------------------------------------------------------------------

Thanks in advance for any help!

Edit2:

Didn't think of including the more detailed crash info (as it didn't show in the crash pop-up, so to say). Anyway, here it is:

Output:

'Jukebox.exe' (Win32): Loaded 'C:\Users\User\Documents\Studier - IT\Objektbaserad programmering i C++\Inlämningsuppgifter\Projekt\Jukebox\Debug\Jukebox.exe'. Symbols loaded.
'Jukebox.exe' (Win32): Loaded 'C:\Windows\SysWOW64\ntdll.dll'. Cannot find or open the PDB file.
'Jukebox.exe' (Win32): Loaded 'C:\Windows\SysWOW64\kernel32.dll'. Cannot find or open the PDB file.
'Jukebox.exe' (Win32): Loaded 'C:\Windows\SysWOW64\KernelBase.dll'. Cannot find or open the PDB file.
'Jukebox.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcp110d.dll'. Symbols loaded.
'Jukebox.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcr110d.dll'. Symbols loaded.
The thread 0xe50 has exited with code 0 (0x0).
Unhandled exception at 0x0083630C in Jukebox.exe: 0xC0000005: Access violation reading location 0x0000003C.

Call stack:

>   Jukebox.exe!Song::getLength() Line 27   C++
    Jukebox.exe!operator<<(std::basic_ostream<char,std::char_traits<char> > & os, const Song & song) Line 59    C++
    Jukebox.exe!Queue::deque(Song & item) Line 55   C++
    Jukebox.exe!Jukebox::playList() Line 493    C++
    Jukebox.exe!Jukebox::play() Line 385    C++
    Jukebox.exe!Jukebox::run() Line 536 C++
    Jukebox.exe!main() Line 547 C++
    Jukebox.exe!__tmainCRTStartup() Line 536    C
    Jukebox.exe!mainCRTStartup() Line 377   C
    kernel32.dll!754d86e3() Unknown
    [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]  
    ntdll.dll!7748bf39()    Unknown
    ntdll.dll!7748bf0c()    Unknown
c++
crash
queue
asked on Stack Overflow May 31, 2014 by SwedishGit • edited Jun 1, 2014 by SwedishGit

1 Answer

0

I think the problem probably is that dequeue is freeing the actual items, because the tmpList is making a shallow copy of the Songlist.

class Queue
{
    private:
        Node *first;
        Node *last;
        int nodes;

This means that the delete n; in dequeue is a mistake. The temporary is simply an object, which has copied int nodes, and first and last pointers. Destroying the data that is pointed to, is the error each node is still retained for use in the main Song list. That's consistent with the symptoms you described, where it works first time and then crashes as soon as you do anything once the playlist is finished.

If you may reduce the Songlist, by calling dequeue on it, then dequeue as it stands needs a flag to make the delete n; conditional. There's a destructor on Queue that you wrote, which tears down a Queue if it goes out of scope, or is passed to delete operator. Fortunately when the tmp list goes out of scope that list is empty, so it doesn't damage the Songlist.

I'm sure the problem was specified, to demonstrate some common issues. The enqueue both storing the Item & adding it to list, rather than seperating storage & queuing concepts, leads to confusion.

The right fix, depends on whether you have reason to suspect you OUGHT to have made a deep copy of the Queue object by a constructor, despite it being less efficient, with Songlist being subject to items dequeued, or if Songlist gets destroyed in one go.

answered on Stack Overflow May 31, 2014 by Rob11311 • edited May 31, 2014 by Rob11311

User contributions licensed under CC BY-SA 3.0