运行此程序时收到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
答案 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
超出范围时,它会自动关闭。