文件未打开,在调试器之外运行会导致段错误 (c++)
你好(提前感谢)
我有点困惑,我似乎无法弄清楚为什么我会出现段错误。
几点说明:
- 这是为了一门课程——遗憾的是我是这样的 需要使用 C 字符串 而不是 std::string。
- 请不要修复我的代码(我不会那样学习,我会继续骚扰你)。 请指出我的逻辑缺陷并建议不同的功能/方式。
- 平台:Suse 上的 gcc 版本 4.4.1 Linux 11.2(2.6.31内核)
以下是代码
main.cpp:
// ///////////////////////////////////////////////////////////////////////////////////
// INCLUDES (C/C++ Std Library)
#include <cstdlib> /// EXIT_SUCCESS, EXIT_FAILURE
#include <iostream> /// cin, cout, ifstream
#include <cassert> /// assert
// ///////////////////////////////////////////////////////////////////////////////////
// DEPENDENCIES (custom header files)
#include "dict.h" /// Header for the dictionary class
// ///////////////////////////////////////////////////////////////////////////////////
// PRE-PROCESSOR CONSTANTS
#define ENTER '\n' /// Used to accept new lines, quit program.
#define SPACE ' ' /// One way to end the program
// ///////////////////////////////////////////////////////////////////////////////////
// CUSTOM DATA TYPES
/// File Namespace -- keep it local
namespace
{
/// Possible program prompts to display for the user.
enum FNS_Prompts
{
fileName_, /// prints out the name of the file
noFile_, /// no file was passed to the program
tooMany_, /// more than one file was passed to the program
noMemory_, /// Not enough memory to use the program
usage_, /// how to use the program
word_, /// ask the user to define a word.
notFound_, /// the word is not in the dictionary
done_, /// the program is closing normally
};
}
// ///////////////////////////////////////////////////////////////////////////////////
// Namespace
using namespace std; /// Nothing special in the way of namespaces
// ///////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/** prompt() prompts the user to do something, uses enum Prompts for parameter.
*/
void prompt(FNS_Prompts msg /** determines the prompt to use*/)
{
switch(msg)
{
case fileName_ :
{
cout << ENTER << ENTER << "The file name is: ";
break;
}
case noFile_ :
{
cout << ENTER << ENTER << "...Sorry, a dictionary file is needed. Try again." << endl;
break;
}
case tooMany_ :
{
cout << ENTER << ENTER << "...Sorry, you can only specify one dictionary file. Try again." << endl;
break;
}
case noMemory_ :
{
cout << ENTER << ENTER << "...Sorry, there isn't enough memory available to run this program." << endl;
break;
}
case usage_ :
{
cout << "USAGE:" << endl
<< " lookup.exe [dictionary file name]" << endl << endl;
break;
}
case done_ :
{
cout << ENTER << ENTER << "like Master P says, \"Word.\"" << ENTER << endl;
break;
}
case word_ :
{
cout << ENTER << ENTER << "Enter a word in the dictionary to get it's definition." << ENTER
<< "Enter \"?\" to get a sorted list of all words in the dictionary." << ENTER
<< "... Press the Enter key to quit the program: ";
break;
}
case notFound_ :
{
cout << ENTER << ENTER << "...Sorry, that word is not in the dictionary." << endl;
break;
}
default :
{
cout << ENTER << ENTER << "something passed an invalid enum to prompt(). " << endl;
assert(false); /// something passed in an invalid enum
}
}
}
/** useDictionary() uses the dictionary created by createDictionary
* - prompts user to lookup a word
* - ends when the user enters an empty word
*/
void useDictionary(Dictionary &d)
{
char *userEntry = new char; /// user's input on the command line
if( !userEntry ) // check the pointer to the heap
{ cout << ENTER << MEM_ERR_MSG << endl; exit(EXIT_FAILURE);
}
do
{
prompt(word_);
// test code
cout << endl << "----------------------------------------" << endl
<< "Enter something: ";
cin.getline(userEntry, INPUT_LINE_MAX_LEN, ENTER);
cout << ENTER << userEntry << endl;
}while ( userEntry[0] != NIL && userEntry[0] != SPACE );
// GARBAGE COLLECTION
delete[] userEntry;
}
/** Program Entry
* Reads in the required, single file from the command prompt.
* - If there is no file, state such and error out.
* - If there is more than one file, state such and error out.
* - If there is a single file:
* - Create the database object
* - Populate the database object
* - Prompt the user for entry
* main() will return EXIT_SUCCESS upon termination.
*/
int main(int argc, /// the number of files being passed into the program
char *argv[] /// pointer to the filename being passed into tthe program
)
{
// EXECUTE
/* Testing code * /
char tempFile[INPUT_LINE_MAX_LEN] = {NIL};
cout << "enter filename: ";
cin.getline(tempFile, INPUT_LINE_MAX_LEN, '\n');
*/
// uncomment after successful debugging
if(argc <= 1)
{
prompt(noFile_); prompt(usage_);
return EXIT_FAILURE; /// no file was passed to the program
}
else if(argc > 2)
{
prompt(tooMany_); prompt(usage_);
return EXIT_FAILURE; /// more than one file was passed to the program
}
else
{
prompt(fileName_); cout << argv[1]; // print out name of dictionary file
if( !argv[1] )
{
prompt(noFile_); prompt(usage_);
return EXIT_FAILURE; /// file does not exist
}
/*
file.open( argv[1] ); // open file
numEntries >> in.getline(file); // determine number of dictionary objects to create
file.close(); // close file
Dictionary[ numEntries ](argv[1]); // create the dictionary object
*/
// TEMPORARY FILE FOR TESTING!!!!
//Dictionary scrabble(tempFile);
Dictionary scrabble(argv[1]); // creaate the dicitonary object
//*/
useDictionary(scrabble); // prompt the user, use the dictionary
}
// exit
return EXIT_SUCCESS; /// terminate program.
}
Dict.h/.cpp
#ifndef DICT_H
#define DICT_H
// ///////////////////////////////////////////////////////////////////////////////////
// DEPENDENCIES (Custom header files)
#include "entry.h" /// class for dictionary entries
// ///////////////////////////////////////////////////////////////////////////////////
// PRE-PROCESSOR MACROS
#define INPUT_LINE_MAX_LEN 256 /// Maximum length of each line in the dictionary file
class Dictionary
{
public :
//
// Do NOT modify the public section of this class
//
typedef void (*WordDefFunc)(const char *word, const char *definition);
Dictionary( const char *filename );
~Dictionary();
const char *lookupDefinition( const char *word );
void forEach( WordDefFunc func );
private :
//
// You get to provide the private members
//
// VARIABLES
int m_numEntries; /// stores the number of entries in the dictionary
Entry *m_DictEntry_ptr; /// points to an array of class Entry
// Private Functions
};
#endif
-----------------------------------
// ///////////////////////////////////////////////////////////////////////////////////
// INCLUDES (C/C++ Std Library)
#include <iostream> /// cout, getline
#include <fstream> // ifstream
#include <cstring> /// strchr
// ///////////////////////////////////////////////////////////////////////////////////
// DEPENDENCIES (custom header files)
#include "dict.h" /// Header file required by assignment
//#include "entry.h" /// Dicitonary Entry Class
// ///////////////////////////////////////////////////////////////////////////////////
// PRE-PROCESSOR MACROS
#define COMMA ',' /// Delimiter for file
#define ENTER '\n' /// Carriage return character
#define FILE_ERR_MSG "The data file could not be opened. Program will now terminate."
#pragma warning(disable : 4996) /// turn off MS compiler warning about strcpy()
// ///////////////////////////////////////////////////////////////////////////////////
// Namespace reference
using namespace std;
// ///////////////////////////////////////////////////////////////////////////////////
// PRIVATE MEMBER FUNCTIONS
/**
* Sorts the dictionary entries.
*/
/*
static void sortDictionary(?)
{
// sort through the words using qsort
}
*/
/** NO LONGER NEEDED??
* parses out the length of the first cell in a delimited cell
* /
int getWordLength(char *str /// string of data to parse
)
{
return strcspn(str, COMMA);
}
*/
// ///////////////////////////////////////////////////////////////////////////////////
// PUBLIC MEMBER FUNCTIONS
/** constructor for the class
* - opens/reads in file
* - creates initializes the array of member vars
* - creates pointers to entry objects
* - stores pointers to entry objects in member var
* - ? sort now or later?
*/
Dictionary::Dictionary( const char *filename )
{
// Create a filestream, open the file to be read in
ifstream dataFile(filename, ios::in );
/*
if( dataFile.fail() )
{ cout << FILE_ERR_MSG << endl; exit(EXIT_FAILURE);
}
*/
if( dataFile.is_open() )
{
// read first line of data
// TEST CODE in.getline(dataFile, INPUT_LINE_MAX_LEN) >> m_numEntries;
// TEST CODE char temp[INPUT_LINE_MAX_LEN] = {NIL};
// TEST CODE dataFile.getline(temp,INPUT_LINE_MAX_LEN,'\n');
dataFile >> m_numEntries; /** Number of terms in the dictionary file
* \todo find out how many lines in the file, subtract one, ingore first line
*/
//create the array of entries
m_DictEntry_ptr = new Entry[m_numEntries];
// check for valid memory allocation
if( !m_DictEntry_ptr )
{ cout << MEM_ERR_MSG << endl; exit(EXIT_FAILURE);
}
// loop thru each line of the file, parsing words/def's and populating entry objects
for(int EntryIdx = 0; EntryIdx < m_numEntries; ++EntryIdx)
{
// VARIABLES
char *tempW_ptr; /// points to a temporary word
char *tempD_ptr; /// points to a temporary def
char *w_ptr; /// points to the word in the Entry object
char *d_ptr; /// points to the definition in the Entry
int tempWLen; /// length of the temp word string
int tempDLen; /// length of the temp def string
char tempLine[INPUT_LINE_MAX_LEN] = {NIL}; /// stores a single line from the file
// EXECUTE
// getline(dataFile, tempLine) // get a "word,def" line from the file
dataFile.getline(tempLine, INPUT_LINE_MAX_LEN); // get a "word,def" line from the file
// Parse the string
tempW_ptr = tempLine; // point the temp word pointer at the first char in the line
tempD_ptr = strchr(tempLine, COMMA); // point the def pointer at the comma
*tempD_ptr = NIL; // replace the comma with a NIL
++tempD_ptr; // increment the temp def pointer
// find the string lengths... +1 to account for terminator
tempWLen = strlen(tempW_ptr) + 1;
tempDLen = strlen(tempD_ptr) + 1;
// Allocate heap memory for the term and defnition
w_ptr = new char[ tempWLen ];
d_ptr = new char[ tempDLen ];
// check memory allocation
if( !w_ptr && !d_ptr )
{ cout << MEM_ERR_MSG << endl; exit(EXIT_FAILURE);
}
// copy the temp word, def into the newly allocated memory and terminate the strings
strcpy(w_ptr,tempW_ptr); w_ptr[tempWLen] = NIL;
strcpy(d_ptr,tempD_ptr); d_ptr[tempDLen] = NIL;
// set the pointers for the entry objects
m_DictEntry_ptr[ EntryIdx ].setWordPtr(w_ptr);
m_DictEntry_ptr[ EntryIdx ].setDefPtr(d_ptr);
}
// close the file
dataFile.close();
}
else
{ cout << ENTER << FILE_ERR_MSG << endl; exit(EXIT_FAILURE);
}
}
/**
* cleans up dynamic memory
*/
Dictionary::~Dictionary()
{
delete[] m_DictEntry_ptr; /// thou shalt not have memory leaks.
}
/**
* Looks up definition
*/
/*
const char *lookupDefinition( const char *word )
{
// print out the word ---- definition
}
*/
/**
* prints out the entire dictionary in sorted order
*/
/*
void forEach( WordDefFunc func )
{
// to sort before or now.... that is the question
}
*/
Entry.h/cpp
#ifndef ENTRY_H
#define ENTRY_H
// ///////////////////////////////////////////////////////////////////////////////////
// INCLUDES (C++ Std lib)
#include <cstdlib> /// EXIT_SUCCESS, NULL
// ///////////////////////////////////////////////////////////////////////////////////
// PRE-PROCESSOR MACROS
#define NIL '\0' /// C-String terminator
#define MEM_ERR_MSG "Memory allocation has failed. Program will now terminate."
// ///////////////////////////////////////////////////////////////////////////////////
// CLASS DEFINITION
class Entry
{
public:
Entry(void) : m_word_ptr(NULL), m_def_ptr(NULL) { /* default constructor */ };
void setWordPtr(char *w_ptr); /// sets the pointer to the word - only if the pointer is empty
void setDefPtr(char *d_ptr); /// sets the ponter to the definition - only if the pointer is empty
/// returns what is pointed to by the word pointer
char getWord(void) const { return *m_word_ptr; }
/// returns what is pointed to by the definition pointer
char getDef(void) const { return *m_def_ptr; }
private:
char *m_word_ptr; /** points to a dictionary word */
char *m_def_ptr; /** points to a dictionary definition */
};
#endif
--------------------------------------------------
// ///////////////////////////////////////////////////////////////////////////////////
// DEPENDENCIES (custom header files)
#include "entry.h" /// class header file
// ///////////////////////////////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS
/*
* only change the word member var if it is in its initial state
*/
void Entry::setWordPtr(char *w_ptr)
{
if(m_word_ptr == NULL)
{ m_word_ptr = w_ptr;
}
}
/*
* only change the def member var if it is in its initial state
*/
void Entry::setDefPtr(char *d_ptr)
{
if(m_def_ptr == NULL)
{ m_word_ptr = d_ptr;
}
}
Hello (and thanks in advance)
I'm in a bit of a quandry, I cant seem to figure out why I'm seg faulting.
A couple of notes:
- It's for a course -- and sadly I am
required to use use C-strings
instead of std::string. - Please dont fix my code (I wont learn that way and I will keep bugging you).
please just point out the flaws in my logic and suggest a different function/way. - platform: gcc version 4.4.1 on Suse
Linux 11.2 (2.6.31 kernel)
Here's the code
main.cpp:
// ///////////////////////////////////////////////////////////////////////////////////
// INCLUDES (C/C++ Std Library)
#include <cstdlib> /// EXIT_SUCCESS, EXIT_FAILURE
#include <iostream> /// cin, cout, ifstream
#include <cassert> /// assert
// ///////////////////////////////////////////////////////////////////////////////////
// DEPENDENCIES (custom header files)
#include "dict.h" /// Header for the dictionary class
// ///////////////////////////////////////////////////////////////////////////////////
// PRE-PROCESSOR CONSTANTS
#define ENTER '\n' /// Used to accept new lines, quit program.
#define SPACE ' ' /// One way to end the program
// ///////////////////////////////////////////////////////////////////////////////////
// CUSTOM DATA TYPES
/// File Namespace -- keep it local
namespace
{
/// Possible program prompts to display for the user.
enum FNS_Prompts
{
fileName_, /// prints out the name of the file
noFile_, /// no file was passed to the program
tooMany_, /// more than one file was passed to the program
noMemory_, /// Not enough memory to use the program
usage_, /// how to use the program
word_, /// ask the user to define a word.
notFound_, /// the word is not in the dictionary
done_, /// the program is closing normally
};
}
// ///////////////////////////////////////////////////////////////////////////////////
// Namespace
using namespace std; /// Nothing special in the way of namespaces
// ///////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/** prompt() prompts the user to do something, uses enum Prompts for parameter.
*/
void prompt(FNS_Prompts msg /** determines the prompt to use*/)
{
switch(msg)
{
case fileName_ :
{
cout << ENTER << ENTER << "The file name is: ";
break;
}
case noFile_ :
{
cout << ENTER << ENTER << "...Sorry, a dictionary file is needed. Try again." << endl;
break;
}
case tooMany_ :
{
cout << ENTER << ENTER << "...Sorry, you can only specify one dictionary file. Try again." << endl;
break;
}
case noMemory_ :
{
cout << ENTER << ENTER << "...Sorry, there isn't enough memory available to run this program." << endl;
break;
}
case usage_ :
{
cout << "USAGE:" << endl
<< " lookup.exe [dictionary file name]" << endl << endl;
break;
}
case done_ :
{
cout << ENTER << ENTER << "like Master P says, \"Word.\"" << ENTER << endl;
break;
}
case word_ :
{
cout << ENTER << ENTER << "Enter a word in the dictionary to get it's definition." << ENTER
<< "Enter \"?\" to get a sorted list of all words in the dictionary." << ENTER
<< "... Press the Enter key to quit the program: ";
break;
}
case notFound_ :
{
cout << ENTER << ENTER << "...Sorry, that word is not in the dictionary." << endl;
break;
}
default :
{
cout << ENTER << ENTER << "something passed an invalid enum to prompt(). " << endl;
assert(false); /// something passed in an invalid enum
}
}
}
/** useDictionary() uses the dictionary created by createDictionary
* - prompts user to lookup a word
* - ends when the user enters an empty word
*/
void useDictionary(Dictionary &d)
{
char *userEntry = new char; /// user's input on the command line
if( !userEntry ) // check the pointer to the heap
{ cout << ENTER << MEM_ERR_MSG << endl; exit(EXIT_FAILURE);
}
do
{
prompt(word_);
// test code
cout << endl << "----------------------------------------" << endl
<< "Enter something: ";
cin.getline(userEntry, INPUT_LINE_MAX_LEN, ENTER);
cout << ENTER << userEntry << endl;
}while ( userEntry[0] != NIL && userEntry[0] != SPACE );
// GARBAGE COLLECTION
delete[] userEntry;
}
/** Program Entry
* Reads in the required, single file from the command prompt.
* - If there is no file, state such and error out.
* - If there is more than one file, state such and error out.
* - If there is a single file:
* - Create the database object
* - Populate the database object
* - Prompt the user for entry
* main() will return EXIT_SUCCESS upon termination.
*/
int main(int argc, /// the number of files being passed into the program
char *argv[] /// pointer to the filename being passed into tthe program
)
{
// EXECUTE
/* Testing code * /
char tempFile[INPUT_LINE_MAX_LEN] = {NIL};
cout << "enter filename: ";
cin.getline(tempFile, INPUT_LINE_MAX_LEN, '\n');
*/
// uncomment after successful debugging
if(argc <= 1)
{
prompt(noFile_); prompt(usage_);
return EXIT_FAILURE; /// no file was passed to the program
}
else if(argc > 2)
{
prompt(tooMany_); prompt(usage_);
return EXIT_FAILURE; /// more than one file was passed to the program
}
else
{
prompt(fileName_); cout << argv[1]; // print out name of dictionary file
if( !argv[1] )
{
prompt(noFile_); prompt(usage_);
return EXIT_FAILURE; /// file does not exist
}
/*
file.open( argv[1] ); // open file
numEntries >> in.getline(file); // determine number of dictionary objects to create
file.close(); // close file
Dictionary[ numEntries ](argv[1]); // create the dictionary object
*/
// TEMPORARY FILE FOR TESTING!!!!
//Dictionary scrabble(tempFile);
Dictionary scrabble(argv[1]); // creaate the dicitonary object
//*/
useDictionary(scrabble); // prompt the user, use the dictionary
}
// exit
return EXIT_SUCCESS; /// terminate program.
}
Dict.h/.cpp
#ifndef DICT_H
#define DICT_H
// ///////////////////////////////////////////////////////////////////////////////////
// DEPENDENCIES (Custom header files)
#include "entry.h" /// class for dictionary entries
// ///////////////////////////////////////////////////////////////////////////////////
// PRE-PROCESSOR MACROS
#define INPUT_LINE_MAX_LEN 256 /// Maximum length of each line in the dictionary file
class Dictionary
{
public :
//
// Do NOT modify the public section of this class
//
typedef void (*WordDefFunc)(const char *word, const char *definition);
Dictionary( const char *filename );
~Dictionary();
const char *lookupDefinition( const char *word );
void forEach( WordDefFunc func );
private :
//
// You get to provide the private members
//
// VARIABLES
int m_numEntries; /// stores the number of entries in the dictionary
Entry *m_DictEntry_ptr; /// points to an array of class Entry
// Private Functions
};
#endif
-----------------------------------
// ///////////////////////////////////////////////////////////////////////////////////
// INCLUDES (C/C++ Std Library)
#include <iostream> /// cout, getline
#include <fstream> // ifstream
#include <cstring> /// strchr
// ///////////////////////////////////////////////////////////////////////////////////
// DEPENDENCIES (custom header files)
#include "dict.h" /// Header file required by assignment
//#include "entry.h" /// Dicitonary Entry Class
// ///////////////////////////////////////////////////////////////////////////////////
// PRE-PROCESSOR MACROS
#define COMMA ',' /// Delimiter for file
#define ENTER '\n' /// Carriage return character
#define FILE_ERR_MSG "The data file could not be opened. Program will now terminate."
#pragma warning(disable : 4996) /// turn off MS compiler warning about strcpy()
// ///////////////////////////////////////////////////////////////////////////////////
// Namespace reference
using namespace std;
// ///////////////////////////////////////////////////////////////////////////////////
// PRIVATE MEMBER FUNCTIONS
/**
* Sorts the dictionary entries.
*/
/*
static void sortDictionary(?)
{
// sort through the words using qsort
}
*/
/** NO LONGER NEEDED??
* parses out the length of the first cell in a delimited cell
* /
int getWordLength(char *str /// string of data to parse
)
{
return strcspn(str, COMMA);
}
*/
// ///////////////////////////////////////////////////////////////////////////////////
// PUBLIC MEMBER FUNCTIONS
/** constructor for the class
* - opens/reads in file
* - creates initializes the array of member vars
* - creates pointers to entry objects
* - stores pointers to entry objects in member var
* - ? sort now or later?
*/
Dictionary::Dictionary( const char *filename )
{
// Create a filestream, open the file to be read in
ifstream dataFile(filename, ios::in );
/*
if( dataFile.fail() )
{ cout << FILE_ERR_MSG << endl; exit(EXIT_FAILURE);
}
*/
if( dataFile.is_open() )
{
// read first line of data
// TEST CODE in.getline(dataFile, INPUT_LINE_MAX_LEN) >> m_numEntries;
// TEST CODE char temp[INPUT_LINE_MAX_LEN] = {NIL};
// TEST CODE dataFile.getline(temp,INPUT_LINE_MAX_LEN,'\n');
dataFile >> m_numEntries; /** Number of terms in the dictionary file
* \todo find out how many lines in the file, subtract one, ingore first line
*/
//create the array of entries
m_DictEntry_ptr = new Entry[m_numEntries];
// check for valid memory allocation
if( !m_DictEntry_ptr )
{ cout << MEM_ERR_MSG << endl; exit(EXIT_FAILURE);
}
// loop thru each line of the file, parsing words/def's and populating entry objects
for(int EntryIdx = 0; EntryIdx < m_numEntries; ++EntryIdx)
{
// VARIABLES
char *tempW_ptr; /// points to a temporary word
char *tempD_ptr; /// points to a temporary def
char *w_ptr; /// points to the word in the Entry object
char *d_ptr; /// points to the definition in the Entry
int tempWLen; /// length of the temp word string
int tempDLen; /// length of the temp def string
char tempLine[INPUT_LINE_MAX_LEN] = {NIL}; /// stores a single line from the file
// EXECUTE
// getline(dataFile, tempLine) // get a "word,def" line from the file
dataFile.getline(tempLine, INPUT_LINE_MAX_LEN); // get a "word,def" line from the file
// Parse the string
tempW_ptr = tempLine; // point the temp word pointer at the first char in the line
tempD_ptr = strchr(tempLine, COMMA); // point the def pointer at the comma
*tempD_ptr = NIL; // replace the comma with a NIL
++tempD_ptr; // increment the temp def pointer
// find the string lengths... +1 to account for terminator
tempWLen = strlen(tempW_ptr) + 1;
tempDLen = strlen(tempD_ptr) + 1;
// Allocate heap memory for the term and defnition
w_ptr = new char[ tempWLen ];
d_ptr = new char[ tempDLen ];
// check memory allocation
if( !w_ptr && !d_ptr )
{ cout << MEM_ERR_MSG << endl; exit(EXIT_FAILURE);
}
// copy the temp word, def into the newly allocated memory and terminate the strings
strcpy(w_ptr,tempW_ptr); w_ptr[tempWLen] = NIL;
strcpy(d_ptr,tempD_ptr); d_ptr[tempDLen] = NIL;
// set the pointers for the entry objects
m_DictEntry_ptr[ EntryIdx ].setWordPtr(w_ptr);
m_DictEntry_ptr[ EntryIdx ].setDefPtr(d_ptr);
}
// close the file
dataFile.close();
}
else
{ cout << ENTER << FILE_ERR_MSG << endl; exit(EXIT_FAILURE);
}
}
/**
* cleans up dynamic memory
*/
Dictionary::~Dictionary()
{
delete[] m_DictEntry_ptr; /// thou shalt not have memory leaks.
}
/**
* Looks up definition
*/
/*
const char *lookupDefinition( const char *word )
{
// print out the word ---- definition
}
*/
/**
* prints out the entire dictionary in sorted order
*/
/*
void forEach( WordDefFunc func )
{
// to sort before or now.... that is the question
}
*/
Entry.h/cpp
#ifndef ENTRY_H
#define ENTRY_H
// ///////////////////////////////////////////////////////////////////////////////////
// INCLUDES (C++ Std lib)
#include <cstdlib> /// EXIT_SUCCESS, NULL
// ///////////////////////////////////////////////////////////////////////////////////
// PRE-PROCESSOR MACROS
#define NIL '\0' /// C-String terminator
#define MEM_ERR_MSG "Memory allocation has failed. Program will now terminate."
// ///////////////////////////////////////////////////////////////////////////////////
// CLASS DEFINITION
class Entry
{
public:
Entry(void) : m_word_ptr(NULL), m_def_ptr(NULL) { /* default constructor */ };
void setWordPtr(char *w_ptr); /// sets the pointer to the word - only if the pointer is empty
void setDefPtr(char *d_ptr); /// sets the ponter to the definition - only if the pointer is empty
/// returns what is pointed to by the word pointer
char getWord(void) const { return *m_word_ptr; }
/// returns what is pointed to by the definition pointer
char getDef(void) const { return *m_def_ptr; }
private:
char *m_word_ptr; /** points to a dictionary word */
char *m_def_ptr; /** points to a dictionary definition */
};
#endif
--------------------------------------------------
// ///////////////////////////////////////////////////////////////////////////////////
// DEPENDENCIES (custom header files)
#include "entry.h" /// class header file
// ///////////////////////////////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS
/*
* only change the word member var if it is in its initial state
*/
void Entry::setWordPtr(char *w_ptr)
{
if(m_word_ptr == NULL)
{ m_word_ptr = w_ptr;
}
}
/*
* only change the def member var if it is in its initial state
*/
void Entry::setDefPtr(char *d_ptr)
{
if(m_def_ptr == NULL)
{ m_word_ptr = d_ptr;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
简单问题
容易发现的问题在这里:
第一个问题是,除非 INPUT_LINE_MAX_LEN == 1,否则该行是错误的。
这很容易修复,将声明 og userEntry 更改为:
我看到的第二个问题是:
这是错误的,因为您只为 userEntry 分配一个字符而不是一个字符数组。与上面相同的解决方案。
更好的解决方案是使用托管字符数组(即字符串),
无需分配或删除,并且它会根据需要重新调整大小,因此您无法注销然后结束。
其他担忧:
在 C++ 代码中看到这一点让我脖子上的野兔站了起来:
在 C++ 中使用接口比使用函数指针要容易得多。 (是的,我知道C++没有关键字interface。但是接口的概念在所有语言中都是相同的,它是实现特定契约的类定义)。
您在课堂上进行了太多的内存管理。
我已经可以看到几个内存泄漏(如果我仔细观察,我确信我会发现指向已超出范围的不存在对象的指针)。
现代 C++ 程序中的指针很少。
我敢打赌,如果您停止尝试像 C 程序那样进行手动内存管理,您的大多数问题都会消失。
Dictionary::Dectionary
理想情况下,字典构造函数如下所示:
Easy Problems
The easy problem to spot is here:
The first problem is that unless INPUT_LINE_MAX_LEN == 1 then the line is wrong.
This is easy to fix change the declaration og userEntry to:
The second problem I see is:
Which is wrong because you only allocate a single char not an array of char for userEntry. The same solution as above.
A better solution is to use a managed array of characters (i.e. a string)
No need to allocate or delete and it re-sizes as required so you can't write off then end.
Other worries:
Seeing this in C++ code makes the hares on the back of my nech stand up:
In C++ it is much easier to use interfaces rather than function pointers. (Yes I know C++ does not have the keyword interface. But the concept of an interface is the same in all languages it is a class definition that implements a specific contract).
You do way too much memory management in the class.
I can already see several memory leaks (if I look harder I am sure I will spot pointers to non existant objects that have gone out of scope).
A modern C++ program will have very few pointers in it.
I will bet most of your problems will disapear if you stop trying to do manual memory management like this was a C program.
Dictionary::Dectionary
Ideally the dictionary constructor woudl look like this:
上一篇文章指出了段错误可能的直接原因,您需要 INPUT_LINE_MAX_LEN+1 个字节来存储输入。但在这个函数中,首先没有理由进行 new/delete,只需使用 char userEntry[INPUT_LINE_MAX_LEN+1];在堆栈上
另请注意,确实存在内存泄漏 - Entry 类拥有指针,但不会删除它们。由于您没有复制任何内容,因此只需将删除语句添加到此类即可。
我希望这个分配的目的是说明为什么我们在现代 C++ 中避免 new[]/delete[] 等。如果这是一门 Java 课程,这就像在 AWT 1.0 中编写一些东西只是为了演示为什么它在几年前被替换。事实是,许多讲师之所以是讲师,是因为他们可以自称使用 C++“超过 15 年”。遗憾的是,这通常意味着“我像 1995 年一样编写 C++”。
为使用这些库的 C++ 初学者选择“加速 C++”。
The previous post picked out the likely immedate cause of the segfault, you need INPUT_LINE_MAX_LEN+1 bytes to store the input. But in this function there is no reason nto new/delete in the first place, just use char userEntry[INPUT_LINE_MAX_LEN+1]; on the stack
Also note that you do have a memory leaks -- the Entry class owns the pointers, but does not delete them. Since you are not copying anything, then just adding the delete statements to this class will work.
I hope that the intent of this assigment is to illustrate just why we avoid new[]/delete[] and the ilk in modern C++. If this were a Java course, this would be like programming something in AWT 1.0 just to demonstrate why it was replaced years ago. The things is, that many instructors are instructors because they can profess to have used C++ "for 15+ years." More often than not, sad to say, this means "I write C++ as if it were 1995."
Pick up "Accelerated C++" for a good beginners into to C++ that uses the libraries.
您为用户输入分配单个字符,但它可能会大得多。使用 char *userEntry = new char[MAX_PATH] 代替
You are allocation single character for user entry, while it could be a lot bigger. Use
char *userEntry = new char[MAX_PATH]
instead