Ниже приведен фрагмент кода из упражнения, над которым я работаю. Он читает CSV и вводит его в связанный список, а затем печатает на консоль. CSV выглядит так:
5,3,19
7,12,2
13,15,25
22,0,7
Он компилируется с использованием Visual Studio 2010 и G ++ как в Linux, так и в Windows. Двоичный файл выполняется в командной строке Windows XP, но возникает ошибка сегментации при запуске в Git Bash (Windows XP) и под Linux. Используя отладчик (под Linux) я изолировал проблему printList()
не распознает конец связанного списка.
Почему это происходит и что я могу сделать, чтобы предотвратить это? Любые предложения будут ценны.
#include <cstdlib>
#include <sstream>
#include <iostream>
#include <fstream>
using namespace std;
// CSV source file parameters
const char *cSourceCSV = "source.csv";
const int iFieldsPerRow = 3;
enum direction_t {UP=1, STATIONARY=0, DOWN=-1};
// struct to hold data in a singly linked list
struct CallList {
float fTime; // time of call in seconds from beginning
int iFromPos;
int iToPos;
direction_t d_tDirectionWanted();
CallList *next;
};
direction_t CallList::d_tDirectionWanted() {
int iBalance = iFromPos - iToPos;
direction_t d_tDirection;
if (iBalance < 0) d_tDirection = DOWN;
else if (iBalance == 0) d_tDirection = STATIONARY;
else if (iBalance > 0) d_tDirection = UP;
return d_tDirection;
}
CallList *head;
CallList *temp;
CallList *work;
void populateList(const char *cSourceCSV) {
string sRow;
string sValue;
ifstream ioSource (cSourceCSV); // the source file placed in an input stream
if (ioSource.is_open()) { // making sure the stream/file is open
while (ioSource.good()) { // repeat while stream is still healthy
// obtain the data
temp = new CallList;
getline (ioSource,sRow); // reading each row of data
stringstream s_sRow(sRow); // now entering the row into a stringstream
for (int i=0; i<iFieldsPerRow; i++) {
ws(s_sRow); // if there is whitespace in s_sRow remove it <-this is
// stopping the program from crashing but I get an extra line 1,1,1
getline (s_sRow,sValue,','); // now getting the data from the
// stringstream using the comma as a delimiter
if (i==0) {
temp->fTime = stof(sValue);
}
else if (i==1) {
temp->iFromPos = stoi(sValue);
}
else if (i==2) {
temp->iToPos = stoi(sValue);
}
}
// the stationary calls are excluded
if (temp->d_tDirectionWanted() == STATIONARY) continue;
// place the remaining data in the linked list
if (head == NULL) {
// insert the head
head = temp;
}
else {
//********* THIS WORKS *************
work = head;
// nothing fancy needed here as list is already in time order
while(work != NULL) {
if (work->next == NULL) {
work->next = temp;
break;
}
work = work->next;
}
}
//************************************
}
ioSource.close();
}
else cout << "Error opening file: " << cSourceCSV << endl;
return;
}
//********* BUT THIS DOESN'T, WHY? *************
void printList(){
work = head;
while (work != NULL) {
printf("Time: %*.1f, From: %*i, To: %*i, Dir: %*i\n", 5, work->fTime, 2, work->iFromPos, 2, work->iToPos, 2, work->d_tDirectionWanted());
if (work->next == NULL) break;
else work = work->next;
}
return;
}
//************************************int main(int argc, char *argv[]) {
populateList(cSourceCSV);
printList();
return 0;
}
Когда вы выделяете свой узел CallList в первый раз, установите next
поле в ноль.
temp = new CallList;
temp->next = NULL;
Ваш printList
пересекает список до work
является NULL
но work
получает свою ценность от next
поле вашего списка узлов, которые никогда не инициализируются. Когда он доходит до конца, последний узел содержит мусор в next
поле и ваша программа умирает.
Почему это нормально в Windows, а не в Linux — это артефакт Неопределенного поведения, который вы получаете, когда пытаетесь получить доступ к неинициализированной переменной.
Других решений пока нет …