C++ 使用指针的访问冲突?-C++;
我为最近的一个学校项目编写了一个使用指针的简单字符串标记化程序。但是,我的C++ 使用指针的访问冲突?-C++;,c++,pointers,tokenize,runtime-error,C++,Pointers,Tokenize,Runtime Error,我为最近的一个学校项目编写了一个使用指针的简单字符串标记化程序。但是,我的StringTokenizer::Next()方法遇到了问题,调用该方法时,应该返回指向char数组中下一个单词的第一个字母的指针。我没有得到编译时错误,但我得到一个运行时错误,该错误声明: Unhandled exception at 0x012c240f in Project 5.exe: 0xC0000005: Access violation reading location 0x002b0000. 程序当前标记
StringTokenizer::Next()
方法遇到了问题,调用该方法时,应该返回指向char数组中下一个单词的第一个字母的指针。我没有得到编译时错误,但我得到一个运行时错误,该错误声明:
Unhandled exception at 0x012c240f in Project 5.exe: 0xC0000005: Access violation reading location 0x002b0000.
程序当前标记字符数组,但随后停止并弹出此错误。我觉得这与我在Next()
方法中执行的NULL
检查有关
那么我该如何解决这个问题呢
此外,如果您注意到我可以做得更有效或更好的实践,请让我知道
谢谢强>
StringTokenizer.h:
#pragma once
class StringTokenizer
{
public:
StringTokenizer(void);
StringTokenizer(char* const, char);
char* Next(void);
~StringTokenizer(void);
private:
char* pStart;
char* pNextWord;
char delim;
};
#include "stringtokenizer.h"
#include <iostream>
using namespace std;
StringTokenizer::StringTokenizer(void)
{
pStart = NULL;
pNextWord = NULL;
delim = 'n';
}
StringTokenizer::StringTokenizer(char* const pArray, char d)
{
pStart = pArray;
delim = d;
}
char* StringTokenizer::Next(void)
{
pNextWord = pStart;
if (pStart == NULL) { return NULL; }
while (*pStart != delim) // access violation error here
{
pStart++;
}
if (pStart == NULL) { return NULL; }
*pStart = '\0'; // sometimes the access violation error occurs here
pStart++;
return pNextWord;
}
StringTokenizer::~StringTokenizer(void)
{
delete pStart;
delete pNextWord;
}
// The PrintHeader function prints out my
// student info in header form
// Parameters - none
// Pre-conditions - none
// Post-conditions - none
// Returns - void
void PrintHeader();
int main ( )
{
const int CHAR_ARRAY_CAPACITY = 128;
const int CHAR_ARRAY_CAPCITY_MINUS_ONE = 127;
// create a place to hold the user's input
// and a char pointer to use with the next( ) function
char words[CHAR_ARRAY_CAPACITY];
char* nextWord;
PrintHeader();
cout << "\nString Tokenizer Project";
cout << "\nyour name\n\n";
cout << "Enter in a short string of words:";
cin.getline ( words, CHAR_ARRAY_CAPCITY_MINUS_ONE );
// create a tokenizer object, pass in the char array
// and a space character for the delimiter
StringTokenizer tk( words, ' ' );
// this loop will display the tokens
while ( ( nextWord = tk.Next ( ) ) != NULL )
{
cout << nextWord << endl;
}
system("PAUSE");
return 0;
}
StringTokenizer.cpp:
#pragma once
class StringTokenizer
{
public:
StringTokenizer(void);
StringTokenizer(char* const, char);
char* Next(void);
~StringTokenizer(void);
private:
char* pStart;
char* pNextWord;
char delim;
};
#include "stringtokenizer.h"
#include <iostream>
using namespace std;
StringTokenizer::StringTokenizer(void)
{
pStart = NULL;
pNextWord = NULL;
delim = 'n';
}
StringTokenizer::StringTokenizer(char* const pArray, char d)
{
pStart = pArray;
delim = d;
}
char* StringTokenizer::Next(void)
{
pNextWord = pStart;
if (pStart == NULL) { return NULL; }
while (*pStart != delim) // access violation error here
{
pStart++;
}
if (pStart == NULL) { return NULL; }
*pStart = '\0'; // sometimes the access violation error occurs here
pStart++;
return pNextWord;
}
StringTokenizer::~StringTokenizer(void)
{
delete pStart;
delete pNextWord;
}
// The PrintHeader function prints out my
// student info in header form
// Parameters - none
// Pre-conditions - none
// Post-conditions - none
// Returns - void
void PrintHeader();
int main ( )
{
const int CHAR_ARRAY_CAPACITY = 128;
const int CHAR_ARRAY_CAPCITY_MINUS_ONE = 127;
// create a place to hold the user's input
// and a char pointer to use with the next( ) function
char words[CHAR_ARRAY_CAPACITY];
char* nextWord;
PrintHeader();
cout << "\nString Tokenizer Project";
cout << "\nyour name\n\n";
cout << "Enter in a short string of words:";
cin.getline ( words, CHAR_ARRAY_CAPCITY_MINUS_ONE );
// create a tokenizer object, pass in the char array
// and a space character for the delimiter
StringTokenizer tk( words, ' ' );
// this loop will display the tokens
while ( ( nextWord = tk.Next ( ) ) != NULL )
{
cout << nextWord << endl;
}
system("PAUSE");
return 0;
}
访问冲突通常意味着指针错误
在这种情况下,最可能的原因是在找到分隔符之前字符串已用完。访问冲突通常意味着指针错误 在这种情况下,最可能的原因是在找到分隔符之前字符串已用完。访问冲突(或某些操作系统上的“分段错误”)表示您试图读取或写入内存中从未分配的位置 考虑Next()中的while循环: 假设字符串是
“blah\0”
。注意,我已经包含了终止null。现在,扪心自问:当循环到达字符串末尾时,它如何知道停止
更重要的是:*pStart
如果循环未能在字符串末尾停止,会发生什么情况?访问冲突(或某些操作系统上的“分段错误”)意味着您试图读取或写入内存中从未分配的位置
考虑Next()中的while循环:
假设字符串是“blah\0”
。注意,我已经包含了终止null。现在,扪心自问:当循环到达字符串末尾时,它如何知道停止
更重要的是:
*pStart
如果循环未能在字符串末尾停止,会发生什么情况?Inside::接下来,您需要检查delim字符,但还需要检查缓冲区的结尾(我猜它由\0表示)
我认为接下来的测试
if (pStart == NULL) { return NULL; }
应该是这个
if (*pStart == '\0') { return NULL; }
也就是说,您应该检查Nul字符,而不是空指针。不清楚这些测试是要检测未初始化的pStart指针还是缓冲区的结尾。Inside::接下来,您需要检查delim字符,但还需要检查缓冲区的结尾(我猜是由\0指示的) 我认为接下来的测试
if (pStart == NULL) { return NULL; }
应该是这个
if (*pStart == '\0') { return NULL; }
也就是说,您应该检查Nul字符,而不是空指针。不清楚这些测试是要检测未初始化的pStart指针还是缓冲区的结尾。此答案基于编辑的问题和其他答案中的各种注释/观察结果提供
首先,调用Next()时pStart的可能状态是什么
if (pStart == NULL) { return NULL; }
为什么我们还不需要担心案例2或案例3呢?您可能希望将相邻分隔符视为它们之间有一个空字符串标记,包括在字符串的开头和结尾。(如果没有,请根据口味进行调整。)while循环将为我们处理该问题,前提是您还添加了“\0”检查(无论是否需要):
在while循环之后,您需要小心。现在可能的状态是什么
delete[]ptr代码>(即数组删除)。其次,您不会同时删除pStart和pNextWord,因为pNextWord指向pStart数组。第三,到最后,pStart不再指向内存的开始,因此需要一个单独的成员来存储delete[]
调用的原始开始。最后,这些数组是在堆栈而不是堆上分配的(即,使用char-var[]
,而不是char*var=new-char[]
),因此不应该删除它们。因此,您应该简单地使用一个空的析构函数
另一个有用的技巧是计算new
和delete
调用的数量;每个都应该有相同的编号。在这种情况下,您有零个new
调用和两个delete
调用,表明问题严重。如果相反,则表示内存泄漏。此答案基于