0

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

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);
}
4

2 回答 2

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()它将把字节存储到一个未定义的内存位置——这被操作系统捕获,它以分段错误终止您的应用程序。


顺便说一句:您应该在编译时考虑启用迂腐警告 - 我编译时使用

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]
于 2013-03-08T08:42:14.647 回答
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);

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

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

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

于 2013-03-08T08:44:13.370 回答