微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C链接列表仅在GNU / Linux而不是Windows中导致分段错误

正在进行的练习下面有一段代码片段.它读取CSV并将其输入链接列表然后打印到控制台. CSV看起来像这样:

5,3,19
7,12,2
13,15,25
22,0,7

它在Linux和Windows中使用Visual Studio 2010和G进行编译.二进制文件在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节点时,将下一个字段设置为null.

temp = new CallList;
temp->next = NULL;

您的printList遍历列表,直到工作为NULL,但工作从列表节点的下一个字段中获取其值,该字段从未初始化.当它到达结尾时,最后一个节点在下一个字段中包含垃圾,程序就会死掉.

为什么这在Windows上是正常的而不是在Linux上是未定义行为的工件,这是当您尝试访问未初始化的变量时获得的.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐