Closed. This question does not meet
Stack Overflow guidelines。它当前不接受答案。
想改善这个问题吗?更新问题,以便将其作为
on-topic用于堆栈溢出。
6年前关闭。
Improve this question
我的第一个问题是在这里问的,所以请谅解如果我没有包含一些内容...
我正在做一个家庭作业项目,该项目基本上包括创建“自动点唱机”(从txt文件导入/导出专辑,创建和“播放”播放列表等)。
我陷入了一点:
当“播放”由自制队列组成的播放列表时,会复制其中的一个副本,并从中取出歌曲并将其打印出来,并有一定的延时。这似乎在程序的第一次运行时运行良好,但是如果再次选择“播放”选项(具有相同的播放列表,则是从其他菜单选项创建的),则在打印第一首歌曲之前会崩溃。如果创建新的播放列表,它也会崩溃,但是在崩溃之前,它会设法打印一些歌曲(似乎取决于第一个/新播放列表中的歌曲数量...)。
使用打印输出,我已经能够跟踪崩溃到在deque函数中的“item = n-> data”调用上了……但是我无法理解为什么会崩溃。
以下是我认为应该相关的代码...如果我包含其他部分,请告诉我。
编辑:崩溃时显示的调试错误是:已调用R6010 abort()
从播放列表播放的方法:
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.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.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.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.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);
}
//---------------------------------------------------------------------------
在此先感谢您的帮助!
编辑2:
没想到要包含更详细的崩溃信息(可以这么说,因为它没有显示在崩溃弹出窗口中)。无论如何,这里是:
输出:
'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.
调用堆栈:
> 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
我认为问题可能在于出队释放了实际的项目,因为tmpList正在制作Songlist的浅拷贝。
class Queue
{
private:
Node *first;
Node *last;
int nodes;
这意味着出队中的
delete n;
是一个错误。临时对象只是一个对象,已复制了int节点以及第一个和最后一个指针。销毁指向的数据是每个节点仍保留在主乐曲列表中以供使用的错误。这与您描述的症状是一致的,它在第一次播放时就起作用,然后在播放列表结束后立即执行任何操作便会崩溃。
如果您可以通过在歌曲列表上调用dequeue来减少Songlist,则按其原样的dequeue需要一个标记来使
delete n;
有条件。您在Queue上编写了一个析构函数,如果超出范围,或将其传递给delete运算符,则它将拆除Queue。幸运的是,当tmp列表超出范围时,该列表为空,因此不会损坏Songlist。
我确定问题已指定,以演示一些常见问题。排队既存储项目又将其添加到列表,而不是分开存储和排队概念,这会引起混乱。
正确的解决方案取决于您是否有理由怀疑自己应该被构造函数构造成Queue对象的深拷贝,尽管效率较低,Songlist会出队,或者Songlist一次被销毁。
我是一名优秀的程序员,十分优秀!