分段错误错误 - C编程

时间:2011-04-19 22:09:21

标签: c++

运行此程序时收到Segmentation Fault错误。总而言之,该程序读入多个数据文件(其中129个)。每个文件都包含有关特定名称的信息。这些信息包括在特定年份中有多少人被命名为特定名称和性别。现在,我试图将每个名称存储在链表中。每当我读取超过4个数据文件时,我都会收到Segmentation Fault错误。我用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 files\n";
      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

3 个答案:

答案 0 :(得分:4)

当然

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

应该是

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

因为您将那么多字符复制到字符串中。 sizeof (length + 1)将在32位计算机上评估为4(64位上为8)。没有分配足够的内存,因此跟随此的strncpy覆盖了不属于您的内存。

答案 1 :(得分:2)

不要找到你的错误,而是试着教你一些实用的课程。以下是C程序员的C ++规则:

1)不要使用指针来跟踪您的数据。标准容器可以正常工作。

2)不要使用指针来管理你的字符串。标准字符串类型适用于此。

3)在你需要了解多态如何工作之前,不要将指针用于其他任何事情。

4)根本不要使用malloc。如初。

5)不要使用新的,几乎没有。

关于不使用指针(或数组)的巧妙之处在于,您永远不会产生指针错误。没有更多的缓冲区溢出,没有更多的分段错误。快乐!

这是我将您的程序翻译成惯用的C ++。因为我让std::list执行所有列表管理,所有愚蠢的headPtr,nextPtr等都会消失。因为我让std::string执行所有字符串管理,所以我不需要malloc(strlen())(或修复我的错误和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 files\n";
      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

答案 2 :(得分:0)

我知道这个已经回答了,但您也应该养成关闭文件的习惯。对于像fclose(filePtr)这样的人。顺便说一下,如果您学习如何使用std::ifstream,那么您不必关闭,当std::ifstream超出范围时,它会自动关闭。