具有std :: list用法的Segfault

时间:2013-03-08 08:29:21

标签: c++ list segmentation-fault push-back

我是Java用户,他正在使用C ++,我很难理解这个语句出了什么问题。在我放置push_back命令的任何地方,我的程序都是segfaulting。所以我想知道到底发生了什么。

class Process {
  public:
    int nice;
    int arrivalTime;
    int cpuBursts;
    list<int> burstList;

    Process() {
      burstList.push_back(10); // Segfaults here...
   }  
}; 

以下是完整代码:

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

using namespace std;

int calcTimeslice(int priority);
int calcOriginalPrio(int nice);
int readFile(int ,char **);
int calcPrioBonus(int,int);
void tokenizeAndAdd(char *);

class Bursts {
  public:
    int isCPUBurst;
    int time;

    Bursts() {}
    // Constructor to make it easier to add to list
    Bursts(int tempIsCPU, int tempTime) {
      isCPUBurst = tempIsCPU;
      time = tempTime;
    }

};

class Process {
  public:
    int nice;
    int arrivalTime;
    int cpuBursts;
    list<int> burstList;

    Process() {
      burstList.push_back(10);
   }
};



int main(int arg, char **argv) {

  // This is if the file was not correctly read into the program
  // or it doesnt exist ...
  if(readFile(arg,argv)==-1) {
    cout << "File could not be read. \n";
    return -1;
  }
  //cout << "Original Calc Whatever: " << calcOriginal(19) << '\n';
  return 0;

}

/*
 *  Calculates the timeslice based on the priority
 */
int calcTimeslice(int priority) {
  double finalCalc;

  // This is the given function in the prompt
  finalCalc = ( (1 - (priority / 140)) * 290 + (.5) ) + 10;

  // Cast to int, this will be a truncate
  return ((int)finalCalc);
}

int readFile(int arg, char **argv) { 
  char *temp,*pointer;
  int endOfFile = 1;

  // While its not the end of the file
  while(endOfFile) {
    // Read in the input from stdin
    fgets(temp,256,stdin);

    // Check to see if this line had a * in it
    if(*temp =='*')
      endOfFile = 0;
    else
      tokenizeAndAdd(temp);
  }

  return 0; 

}

void tokenizeAndAdd(char *string) {
  char *token = strtok(string," \n"); 
  int i = 0;
  Process p;

  while(token != NULL) {
    cout << token << endl;
    if(i>2) {  // If it is odd (CPU burst)
      if(i%2 == 1) {
        int tempInt = atoi(token);
        //p.burstList.push_back(tempInt); 
      }
      else { // If it is even (IO burst)
        int tempInt = atoi(token);
        //p.burstLis.push_back(tempInt); 
      }      
    }
    else if(i==0)
      p.nice = atoi(token);
    else if(i==1)
      p.arrivalTime = atoi(token);
    else if(i==2)
      p.cpuBursts = atoi(token);

    token = strtok(NULL," \n");
    i++;
  }

  //cout << p.nice << " " << p.arrivalTime << " " << p.cpuBursts << "\n";
  //i = 0;
  //cout << p.burstList.size() << "\n";
  //  cout << 
  //}
  return;
}

/*
 *  Calculates and returns the original priority based on the nice number
 *    provided in the file.
 */
int calcOriginalPrio(int nice) {
  double finalCalc;

  // This is the given function from the prompt
  finalCalc = (( nice + 20 ) / 39 ) * 30 + 105.5;

  // Cast to int, this is a truncate in C++
  return ((int)finalCalc);
}

/* 
 * Calculates the bonus time given to a process
 */
int calcPrioBonus(int totalCPU, int totalIO) {
  double finalCalc;

  // How to calculate bonus off of the prompt
  if(totalCPU < totalIO)
    finalCalc = ( (1 - (totalCPU / (double)totalIO)) * (-5)) - .5;
  else
    finalCalc = ( (1 - (totalIO / (double)totalCPU)) * 5) + .5;

  // Cast to int
  return ((int)finalCalc);
}

2 个答案:

答案 0 :(得分:2)

您在以下代码中使用temp未初始化:

char *temp;
...
while(endOfFile) {
  fgets(temp,256,stdin);
  ...

这可能有任何副作用,因为它很可能会破坏您的堆栈或堆内存的一部分。它可能会立即失败(在调用fgets()函数时),它可能会在以后失败(如在您的示例中)或者它甚至可能运行正常 - 可能直到您升级操作系统,编译器或其他任何东西,或者直到您想要在另一台机器上运行相同的可执行文件这称为未定义的行为

您需要为temp变量分配空间,而不是仅为指针。使用像

这样的东西
char temp[256];
...
while(endOfFile) {
  fgets(temp,256,stdin);
  ...

有关详细信息,请参阅fgets()文档。第一个参数是一个指向char数组的指针 - 这是fgets()将存储已读取的字节的位置。在你的代码中,你传递一个未初始化的指针,这意味着fgets()将把字节存储到一个未定义的内存位置 - 操作系统会捕获这些内容,从而终止你的应用程序出现分段错误。


BTW:你应该考虑在编译时启用迂腐警告 - 我用

编译
g++ -Wall -pedantic -o list list.cpp

给了我以下警告:

list.cpp: In function 'int readFile(int, char**)':
list.cpp:76:26: warning: 'temp' may be used uninitialized in this function [-Wuninitialized]

答案 1 :(得分:0)

这可能不是您报告错误的实际代码。但这是给你UB的一个问题。

  char *temp,*pointer; // uninicialized pointer  char temp[1000]; could work?
  int endOfFile = 1;

  // While its not the end of the file
  while(endOfFile) {
    // Read in the input from stdin
    fgets(temp,256,stdin);

最后一个函数调用将从stdin读取最多256个字节,并将其写入指针tmp指向的内存中。所以,你需要先“准备”那个记忆。但是用char * tmp;你只定义一个指针,没有定义的值,也就是说,指向一些可能存在的或者非法/不可访问你的内存。相反,char tmp [1000];将在“堆栈内存”中定义一个1000字节的块,您可以指向使用简单的变量tmp。希望这对你来说很清楚。
编辑:

I don't know why that would change the behavior of the list, 

你是对的。那就是Undefined Behavior(UB)。当您在一些未知的内存中写入时(由未初始化的指针指向),您可能会以不可预测的方式覆盖数据甚至代码,这些代码会破坏程序的正确功能。 您将需要了解有关指针的更多信息,但最好使用std :: string,并查看如何使用字符串和stringstream解析文件。这将为你管理记忆,