分段错误- C编程

Segmentation fault error - C programming

本文关键字:编程 错误 分段      更新时间:2023-10-16

当我运行这个程序时,我收到一个分段错误。总而言之,该程序读取多个数据文件(其中129个)。每个文件包含一个特定名称的信息。这些信息包括有多少人在特定年份被命名为特定名字以及性别。现在,我试图将每个名字存储在一个链表中。每当我读取超过4个数据文件,我得到分割错误错误。我用Java编写了这个程序,它要简单得多。如果有人可以简单地指出我在正确的方向,因为我几乎肯定这与内存分配有关,但我似乎无法解决这个问题。谢谢你。

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <string.h>
#include <cstdlib>
using namespace std;
//typedef struct Node NodeStruct;
struct Node {
  char *namePtr;
  Node *nextPtr;
};
int main() {
  // Declare variables 
  Node *headPtr = NULL;
  Node *tempPtr;
  Node *currentPtr;
  // Variables for reading in a file
  FILE *filePtr;
  char fileName[20];
  int i;
  int nameLength;
  char inputLine[81];
  cout << "Reading from data files, please be patient...n";
  // Loop through files
  for (i = 1880; i <= 2009; i++) {
    sprintf(fileName, "data/yob%d.txt", i);
    filePtr = fopen(fileName, "r");    // Open the file
    // Check to ensure file was opened
    if(filePtr == NULL) {
      cout << "Error opening input file...check location of data filesn";
      exit(-1);   // Exit program
    } // End if statement
    while (fscanf(filePtr, "%s", inputLine) != EOF) {
      // Create a node
      tempPtr = (Node *) malloc(sizeof(Node));
      tempPtr->nextPtr = NULL;
      // Set the head pointer of first node
      if (headPtr == NULL) {
    headPtr = tempPtr;
    currentPtr = tempPtr;
      } // End if statement
      // Link the list
      currentPtr->nextPtr = tempPtr;
      currentPtr = currentPtr->nextPtr;
      // Create pointer variables
      char *startPtr = inputLine;
      char *endPtr = NULL;
      endPtr = strchr(inputLine, ',');   // Point to end of name
      int length = endPtr - inputLine;      // Calculate length
      // Create space for the name
      tempPtr->namePtr = (char *) malloc(sizeof(length + 1));
      strncpy(tempPtr->namePtr, startPtr, length); // Store pointer to name
      //      cout << tempPtr->namePtr << endl;
    }
  } // End of for (i = 1880...
  cout << "Done reading from data files...n";
} // End of main function

当然

tempPtr->namePtr = (char *) malloc(sizeof(length + 1));
应该

tempPtr->namePtr = (char *) malloc(length + 1);

,因为你复制了那么多字符到字符串。在32位计算机上,sizeof (length + 1)的值为4(在64位计算机上为8)。没有分配足够的内存,所以后面的strncpy覆盖了不属于您的内存。

与其找bug,不如教你一些实践经验。以下是我给C程序员的c++规则:

1)不要使用指针来跟踪你的数据。标准的容器可以很好地解决这个问题。

2)不要使用指针来管理字符串。标准的字符串类型可以很好地解决这个问题。

3)除非你需要了解多态性是如何工作的,否则不要将指针用于其他用途。

4)不要使用malloc。。

不要用new,几乎不用。

不使用指针(或数组)的好处是,你永远不会产生指针错误。没有更多的缓冲区溢出,没有更多的分段错误。快乐!

这是我把你的程序翻译成习惯的c++。因为我让std::list做所有的列表管理,所有愚蠢的headPtr, nextPtr等都消失了。因为我让std::string做所有的字符串管理,我不需要malloc(strlen())(或修复我的bug和malloc(strlen()+1))。因为我使用了RAII的习惯用法,所以我不必担心关闭我的文件。

一切正常。

#include <iostream>
#include <fstream>
#include <string>
#include <list>
#include <cstdlib>
#include <sstream>
using std::string;
using std::cout;
using std::list;
using std::ifstream;
using std::stringstream;
int main() {
  // Declare variables 
  list<string> list;
  cout << "Reading from data files, please be patient...n";
  // Loop through files
  for (int i = 1880; i <= 2009; i++) {
    stringstream fileName;
    fileName << "data/yob" << i << ".txt";
    ifstream filePtr(fileName.str().c_str());
    if(!filePtr.is_open()) {
      cout << "Error opening input file: " << fileName.str() << " ...check location of data filesn";
      exit(-1);   // Exit program
    }
    string inputLine;
    while (filePtr >> inputLine) {
      list.push_back(inputLine);
    }
  } // End of for (i = 1880...
  cout << "Done reading from data files...n";
} // End of main function

我知道这个问题已经有了答案,但是您也应该养成关闭文件的习惯。像fclose(filePtr)这样的东西。顺便说一下,如果你学会了如何使用std::ifstream,那么你就不必关闭,当std::ifstream超出作用域时,它会自动关闭。