我用c ++编写了一个简单的测试程序,但为什么会崩溃:
s[i] = s[i] - 'a' + 'A';
Run Code Online (Sandbox Code Playgroud)
例外:访问冲突写入位置0x01327808
#include "stdafx.h"
#include <iostream>
using namespace std;
class String
{
public:
char *s;
int len();
void upper();
String(char*);
};
String::String(char*x)
{
s = x;
}
int String::len()
{
return strlen(s);
}
void String::upper()
{
for (int i = 0; i < len(); i++)
{
if (s[i] >= 'a' && s[i] <= 'z')
{
cout << s[i] << endl;
s[i] = s[i] - 'a' + 'A';
}
}
};
int main()
{
String s("test");
s.upper();
cout << s.len() << endl;
cout << s.s << endl;
system("pause");
}
Run Code Online (Sandbox Code Playgroud)
pax*_*blo 10
这是因为:
String s("test");
Run Code Online (Sandbox Code Playgroud)
这样做是为了传递const char * "test"给你的构造函数,然后只是存储该字符串的地址.
稍后,当您尝试修改指针指向的内存时,这是未定义的行为.
通常,字符串文字将存储在只读内存中以允许进行某些优化,并且任何修改它们的尝试都将导致访问冲突.
如果你要改变:
String s("test");
Run Code Online (Sandbox Code Playgroud)
成:
char cp[] = "test";
String s(cp);
Run Code Online (Sandbox Code Playgroud)
你可能会发现它会起作用.
但是,你的类应该真正为它自己的目的制作一个字符串的副本 - 仅仅指针是不安全的,因为传递给你指针的代码也可以改变它的内容.
您应该在代码中更改的内容,以使其更安全:
s 应该是私人会员,而不是公共会员.s = new char[strlen(x)+1];strcpy (s,x);.String::~String() { delete[] s; }.const char *(因为你没有改变它).toupper(ch)而不是ch - 'a' + 'A'.虽然您的公式适用于ASCII,但我不相信它符合标准.cout应该由类处理,而不是在它之外的代码处理(一旦你s私有,这将是强制性的.