分段错误(核心转储) - 代码在VS中工作,但不在Linux终端中

问题描述:

因此,我可以在Visual Studio中运行此程序,但绝对没有问题,可以生成正确的输出。但是,在Linux终端中编译后,尝试运行相同的代码时出现seg故障。在使用GDB进行调试时,给出的信息不是很有帮助(将在下面提供)。该程序由两个头文件和三个.cpp文件组成。我将在下面提供它们以及给出的调试信息。 (如果缩进很奇怪,那是因为要提交4空格的代码缩进规则)。我一直试图找到这个问题几个小时结束无济于事。我有一种感觉,这是一个小小的错误。非常感谢你提前。分段错误(核心转储) - 代码在VS中工作,但不在Linux终端中

Song.h

#ifndef Song_h 
#define Song_h 

#include <iostream> 
#include <fstream> 
#include <string> 
#include <ctime> 
#include <stdlib.h> 

using namespace std; 

class Song 
{ 
private: 
    string artist; 
    string title; 
    int size; 

public: 
    Song(); //declares blank song array 

    Song(string _title, string _artist, int _size); //initializes object with given parameters for Song instance 

    string getArtist() const 
    { 
     return artist; 
    } 

    string getTitle() const 
    { 
     return title; 
    } 

    int getSize() const 
    { 
     return size; 
    } 

    void setArtist(string _artist) 
    { 
     artist = _artist; 
    } 

    void setTitle(string _title) 
    { 
     title = _title; 
    } 

    void setSize(int _size) 
    { 
     size = _size; 
    } 


    bool operator == (Song const &rhs); 

    bool operator != (Song const &rhs); 

    bool operator > (Song const &rhs); 

    bool operator < (Song const &rhs); 

}; 

#endif 

TsuPod.h

#ifndef TsuPod_h 
#define TsuPod_h 
#include "Song.h" 

//TsuPod class declaration 
class TsuPod 
{ 
private: 
struct SongNode 
{ 
    Song data; 
    SongNode *next; 
}; 

SongNode *songs; //the head pointer 

static const int MAX_SIZE = 512; 
static const int SUCCESS = 0; 
static const int FAILURE = 1; 
static const int NO_MEMORY = -1; 
static const int NOT_FOUND = -2; 
int getNumSongs(); 
int memSize; 

public: 
TsuPod(); 
TsuPod(int size); 
~TsuPod(); 
int addSong(Song const &s); 
int removeSong(Song const &s); 
void shuffle(); 
void showSongList(); 
void sortSongList(); 
int getRemainingMemory(); 

int getTotalMemory() 
{ 
    return memSize; 
} 
}; 

Song.cpp

#endif 

#include "TsuPod.h" 
#include "Song.h" 

Song::Song() //default constructor, initializes a blank song 
{ 
artist = ""; 
title = ""; 
size = 0; 
} 

Song::Song(string _artist, string _title, int _size) //constructor for song when arguments are given by user 
{ 
artist = _artist; 
title = _title; 
size = _size; 
} 

bool Song::operator == (Song const &rhs) //overloaded for sorting 
{ 
return (title == rhs.title && 
     artist == rhs.artist && 
     size == rhs.size); 
} 

bool Song::operator != (Song const &rhs) //overloaded for sorting 
{ 
return (title != rhs.title || 
    artist != rhs.artist || 
    size != rhs.size); 
} 

bool Song::operator > (Song const &rhs) //overloaded for sorting 
{ 
if (artist != rhs.artist) 
    return (artist > rhs.artist); 
else 
if (title != rhs.title) 
    return (title > rhs.title); 
else 
if (size != rhs.size) 
    return (size > rhs.size); 
else 
    return false; 
} 

bool Song::operator < (Song const &rhs) //overloaded for sorting 
{ 
if (artist != rhs.artist) 
    return (artist < rhs.artist); 
else 
if (title != rhs.title) 
    return (title < rhs.title); 
else 
if (size != rhs.size) 
    return (size < rhs.size); 
else 
    return false; 

} 

TsuPod.cpp

#include "TsuPod.h" 
#include "Song.h" 


TsuPod::TsuPod() //default constructor 
{ 
memSize = MAX_SIZE; 
} 

TsuPod::TsuPod(int _size) //constructor for when user specifies their prefered memory size, prevents input of a size greater than MAX_SIZE or less than 0 
{ 
if (_size > MAX_SIZE || _size <= 0) 
    memSize = MAX_SIZE; 
else 
    memSize = _size; 
} 

TsuPod::~TsuPod() //destructor 
{ 
SongNode *p; 

while (songs != NULL) 
{ 
    p = songs; 
    songs = songs->next; 
    delete p; 
} 
} 


int TsuPod::getRemainingMemory() //finds remaining memory, returns int value 
{ 
int memSum = 0; 
SongNode *p = songs; 

while (p != NULL) 
{ 
    memSum += p->data.getSize(); 
    p = p->next; 
} 
return memSize - memSum; 
} 

int TsuPod::addSong(Song const &s) //adds song to TsuPod, returns int number to display result, 0 = success, 1 = failure, -1 = not enough memory 
{ 
if (s.getSize() > getRemainingMemory()) //ensures there is enough unsused memory for song 
    return NO_MEMORY; 

if (s.getSize() > 0) //ensures song is valid 
{ 
    SongNode *temp = new SongNode; 
    temp->data = s; 
    temp->next = songs; 
    songs = temp; 
    return SUCCESS; 
} 

else 
    return FAILURE; 

} 


int TsuPod::removeSong(Song const &s) //removes song, returns int value to display result, 0 = success, 1 = failure, -2 = not found 
{ 
if (songs != NULL) 
{ 
    SongNode *prev = NULL; 
    SongNode *p = songs; 

    if (p->data == s) 
    { 
     songs = p->next; 
     return SUCCESS; 
    } 

    while (p != NULL && p->data != s) 
    { 
     prev = p; 
     p = p->next; 

     if (songs->data == s) 
     { 
      songs = p->next; 
      delete p; 
      return SUCCESS; 
     } 

     else 
     if (p->data == s) 
     { 
      prev->next = p->next; 
      delete p; 
      return SUCCESS; 
     } 
     else 
     { 

     } 
    } 
} 
return NOT_FOUND; 
} 

int TsuPod::getNumSongs() //calculates number of songs, returns int value 
{ 
SongNode *p1 = songs; 
int i = 0; 
while (p1 != NULL) 
{ 
    i++; 
    p1 = p1->next; 
} 

return i; 
} 

void TsuPod::shuffle() //shuffles TsuPod song list, void return value 
{ 
srand((unsigned)time(NULL)); 
for (int j = 0; j < getNumSongs() * 2; j++) 
{ 
    int r1 = rand() % getNumSongs(); 
    int r2 = rand() % getNumSongs(); 

    SongNode *p1 = songs; 
    SongNode *p2 = songs; 

    for (int i = 0; i < r1; i++) 
     p1 = p1->next; 

    for (int i = 0; i < r2; i++) 
     p2 = p2->next; 

    Song temp = p1->data; 
    p1->data = p2->data; 
    p2->data = temp; 
} 

cout << endl << " PLAYLIST SHUFFLED" << endl << endl; 
} 

void TsuPod::sortSongList() //sorts song list by artist, title, and size respectively, void return value 
{ 
for (SongNode *p1 = songs; p1 != NULL; p1 = p1->next) 
{ 
    SongNode *small = p1; 
    for (SongNode *p2 = p1->next; p2 != NULL; p2 = p2->next) 
    { 
     if (small->data > p2->data) 
     { 
      small = p2; 
     } 
    } 

    if (p1 != small) 
    { 
     Song temp = small->data; 
     small->data = p1->data; 
     p1->data = temp; 
    } 
} 
cout << endl << " PLAYLIST SORTED" << endl; 
} 

void TsuPod::showSongList() //shows song list, void return value 
{ 
cout << "    ___________________________________________________     " << endl << "        TsuPod 2.0" << endl << endl; 
cout << "   Memory ----     Total: " << getTotalMemory() << " MB" << " -- Remaining: " << getRemainingMemory() << " MB" << endl; 

SongNode *p = songs; 
int i = 0; 
while (p != NULL) 
{ 
    i++; 
    cout << endl << " " << i << ". " << p->data.getArtist(); 

    int artistLength = p->data.getArtist().length(); 
    for (int j = 0; j < (24 - artistLength); j++) //This loop is implemented to evenly space the artist from the song 
     cout << " "; 

    cout << p->data.getTitle(); 

    int titleLength = p->data.getTitle().length(); 
    for (int j = 0; j < (24 - titleLength); j++) //This loop is implemented to evenly space the song title from the song size 
     cout << " "; 

    cout << p->data.getSize() << " (MB)" << endl; 

    p = p->next; 
} 

cout << endl; 

} 

TsuPod_Driver.cpp

#include <cstdlib> 
#include <iostream> 
#include "Song.h" 
#include "TsuPod.h" 

using namespace std; 

int main(int argc, char *argv[]) 
{ 
TsuPod t; 

Song s1("Animals As Leaders", "Another Year", 4); 
int result = t.addSong(s1); 
cout << " add result = " << result << endl; 

Song s2("Gorillaz", "Stylo", 6); 
result = t.addSong(s2); 
cout << " add result = " << result << endl; 

Song s3("August Burns Red", "Meridian", 6); 
result = t.addSong(s3); 
cout << " add result = " << result << endl; 

Song s4("The Ink Spots", "If I Didn't Care", 7); 
result = t.addSong(s4); 
cout << " add result = " << result << endl; 

Song s5("Beatles", "I Feel Fine", 241); 
result = t.addSong(s5); 
cout << " add result = " << result << endl; 

Song s6("Fine Constant", "Sea", 3); 
result = t.addSong(s6); 
cout << " add result = " << result << endl; 

Song s7("Human Abstract", "Nocturne", 9); 
result = t.addSong(s7); 
cout << " add result = " << result << endl; 

Song s8("August Burns Red", "Meridian", 4); 
result = t.addSong(s8); 
cout << " add result = " << result << endl; 

Song s9("Frank Sinatra", "My Way", 5); 
result = t.addSong(s9); 
cout << " add result = " << result << endl; 



t.showSongList(); 
t.shuffle(); 
t.showSongList(); 
t.sortSongList(); 
t.showSongList(); 


result = t.removeSong(s1); 
cout << " delete result = " << result << endl; 

result = t.removeSong(s2); 
cout << " delete result = " << result << endl; 

result = t.removeSong(s3); 
cout << " delete result = " << result << endl; 

t.showSongList(); 

result = t.removeSong(s4); 
cout << " delete result = " << result << endl; 

result = t.removeSong(s5); 
cout << " delete result = " << result << endl; 

result = t.removeSong(s6); 
cout << " delete result = " << result << endl; 

result = t.removeSong(s7); 
cout << " delete result = " << result << endl; 

result = t.removeSong(s8); 
cout << " delete result = " << result << endl; 

result = t.removeSong(s9); 
cout << " delete result = " << result << endl; 

t.showSongList(); 

cout << " memory = " << t.getRemainingMemory() << endl << endl << endl << endl; 

for (int i = 1; i < 33; i++) //tests to ensure that user cannot add a song when there is not enough space available 
{ 
    Song s1("August Burns Red", "Meridian", i); 
    result = t.addSong(s1); 
    cout << " add result = " << result << endl; 
} 

t.showSongList(); 

cin.get(); 
return EXIT_SUCCESS; 

调试信息从Linux终端

Program received signal SIGSEGV, Segmentation fault. 
0x0000000000402d50 in Song::getSize() const() 
(gdb) backtrace 
#0 0x0000000000402d50 in Song::getSize() const() 
#1 0x00000000004024ac in TsuPod::getRemainingMemory()() 
#2 0x00000000004024fb in TsuPod::addSong(Song const&)() 
#3 0x000000000040112e in main() 
+1

由gdb *给出的信息*很有用。它告诉你在调用'getRemainingMemory()'中的'getSize()'时发生崩溃。接下来,您应该在'getRemainingMemory()'上放置一个断点。并检查所有变量。尤其是指针,因为段错误发生时,他们是未初始化... – Leiaz

+0

@Leiaz我解释信息没有用的唯一原因是,这是我第一次使用GDB,并期待更多的信息(行号)。但我绝对明白你现在的意思。感谢您的帮助! – Dante

+0

如果使用调试符号编译(g ++的'-g'选项),它将打印行号。 – Leiaz

我没有看到TsuPod ::歌曲迹象正在初始化。有没有保证,这将是空的空单的情况下,让您的

while (p != NULL) 

试验TsuPod :: getRemainingMemory()可以用疯狂的值传递从堆栈炸毁当你请使用P下一行。

我建议

TsuPod::TsuPod():songs(NULL) //default constructor 
{ 
memSize = MAX_SIZE; 
} 

TsuPod::TsuPod(int _size):songs(NULL) //constructor for when user specifies their prefered memory size, prevents input of a size greater than MAX_SIZE or less than 0 
{ 
if (_size > MAX_SIZE || _size <= 0) 
    memSize = MAX_SIZE; 
else 
    memSize = _size; 
} 

确保歌曲与您的列表结束的条件开始。

此外,请考虑使用std :: list来执行列表管理来代替roll-your-own链接列表。

+0

非常感谢!我希望你不介意我是否会问另一个问题(我对指针还比较陌生)。你的解决方案有效,但为什么在构造函数中将头部的'songs'声明为NULL,而不是在类声明中声明'songs'NULL? – Dante

+0

我不喜欢我的C++ 11或14,我不认为该标准允许您在类定义中进行分配。所有声明保证做的都是预留空间,之后的一切都取决于你。我的理解是Visual Studio的编译器很好,并且将所有东西都初始化为零,但几乎所有的时候,编码器都将这个值设置为先发制人的零值是浪费精力。 – user4581301