关于动态内存的问题

O湛狼O 2010-06-28 10:56:37
#include <iostream>

using namespace std;

class String
{
public:
String( const char * = 0 );
String& operator=(const char*);

private:
int _size;
char *_string;
};

String& String::operator = (const char *pi)
{



cout<<"haha"<<endl;
system("pause");
_size=0;
const char* pt=pi;
while(*pt++)
_size++;
_string=new char[_size+1];
char *str=_string;
while(*str++=*pi++);

return *this;
}

String::String(const char *pi)
{
if(!pi)
{
_size=0;
_string=0;
}
else
{
_size=0;
const char *pt=pi;
while(*pt++)
_size++;

cout<<_size<<endl;

_string=new char[_size];

char *st = _string;

while(*st++ = *pi++);

delete []_string;
}
}


void main()
{


String ab="hello,the world";
char *c="gogogoog";
ab = c;
}


请问错在哪里?我把构造函数里的delete []_string或者while (*st++ = *pi++); 去掉就没错了。为什么?先别在程序上挑毛病,我想知道这里为什么会有错,申请了动态内存,然后释放掉有什么错呢?
...全文
206 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
O湛狼O 2010-07-02
  • 打赏
  • 举报
回复
谢谢!
livedrm 2010-06-30
  • 打赏
  • 举报
回复
构造函数中
_string=new char[_size];
应该为
_string=new char[_size+1];
否则
while(*st++ = *pi++);
最后一步循环在未申请的内存赋值,属于未定义行为,可能在别的系统上不会出错,看运气。所以O啦
doublemoon 2010-06-30
  • 打赏
  • 举报
回复
using namespace std;

class String
{
public:
String( const char * = 0 );
String& operator=(const char*);

private:
int _size;
char *_string;
};

String& String::operator = (const char *pi)
{
cout<<"haha"<<endl;
system("pause");
_size=0;
const char* pt=pi;
while(*pt++)
_size++;
_string=new char[_size+1];
char *str=_string;
while(*str++=*pi++);

return *this;
}

String::String(const char *pi)
{
if(!pi)
{
_size=0;
_string=0;
}
else
{
_size=0;
const char *pt=pi;
while(*pt++) //此处算出来的大小,不包括'\0'
_size++;

cout<<_size<<endl;

_string=new char[_size+1]; //由于不包括'\0',所以你new出来的的大小需要加1

char *st = _string;

while( *st++ = *pi++) //由于你没有加1,所以此处访问越界了
;

delete []_string; //删除一个越界指针,肯定会出错的
}
}


void main()
{
String ab="hello,the world";
char *c="gogogoog";
ab = c;
}
doublemoon 2010-06-30
  • 打赏
  • 举报
回复
[code=C/C++]using namespace std;

class String
{
public:
String( const char * = 0 );
String& operator=(const char*);

private:
int _size;
char *_string;
};

String& String::operator = (const char *pi)
{
cout<<"haha"<<endl;
system("pause");
_size=0;
const char* pt=pi;
while(*pt++)
_size++;
_string=new char[_size+1];
char *str=_string;
while(*str++=*pi++);

return *this;
}

String::String(const char *pi)
{
if(!pi)
{
_size=0;
_string=0;
}
else
{
_size=0;
const char *pt=pi;
while(*pt++) //此处算出来的大小,不包括'\0'
_size++;

cout<<_size<<endl;

_string=new char[_size+1]; //由于不包括'\0',所以你new出来的的大小需要加1

char *st = _string;

while( *st++ = *pi++) //由于你没有加1,所以此处访问越界了
;

delete []_string; //删除一个越界指针,肯定会出错的
}
}


void main()
{
String ab="hello,the world";
char *c="gogogoog";
ab = c;
}code]
huhacn 2010-06-30
  • 打赏
  • 举报
回复
对于动态分配的内存,越界操作后,再调用delete[]操作,就会报错
楼主的错误即下面的错误:
char *p = new char[1024];
memset(p, 0, 1024+1);//while(*st++ = *pi++)
delete []p;
Zeilone 2010-06-30
  • 打赏
  • 举报
回复
new出来的空间大小不对,还要加上字符串最后的结束符
比如你的字符串是10个字符
你只new出来10个字节的空间
while(*st++ = *pi++)时,到最后的结束符会写到第十一个字节
所以就会出现访问错误
mofeellassie 2010-06-30
  • 打赏
  • 举报
回复
改为这样就行了while(*st++ = *pi++ && *pi !=NULL);
确实已经越界了
winterlc 2010-06-30
  • 打赏
  • 举报
回复
代码问题很多呀,拿出来根本没法用。
delete []_string; _string做为成员变量,delete后要置为NULL。而且就算你在这里删除,_size的值还是大于0的。
然后其他问题大家都提过了
O湛狼O 2010-06-29
  • 打赏
  • 举报
回复
只有5楼说得靠谱,我想知道的是为什么错。谢谢了。而7楼,我不是说我要把那句注释掉,然后继续用这个程序,我的意思是错误可能就在那句上,我想弄明白为什么注释掉那句就不会出错,5楼就说的清楚了,因为那句已经越界访问了。
zhoulingj 2010-06-29
  • 打赏
  • 举报
回复
while(*st++ = *pi++);

的确是越界了,如果你想根据*pi==0去让循环结束,就显示的写出来嘛,不然看起来也麻烦。
ForestDB 2010-06-29
  • 打赏
  • 举报
回复
帮顶。
cattycat 2010-06-28
  • 打赏
  • 举报
回复
delete []_string;
应该放在析构函数中,构造函数怎么能delete呢。
pengzhixi 2010-06-28
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 lijiantao923 的回复:]
引用 1 楼 pengzhixi 的回复:
_string=new char[_size];

char *st = _string;

while(*st++ = *pi++);

delete []_string;//你这里就将内存释放了,那后面就不能对_string所指的内存进行操作了。


不是这个问题,你试下把while(*st++ = *pi++);这句注释掉,就不……
[/Quote]
如果你打算考人品吃饭的话,你大可以这么用。至于while(*st++ = *pi++);你完全可以使用strncpy
yunyun1886358 2010-06-28
  • 打赏
  • 举报
回复
这样:

#include <iostream>

using namespace std;

class String
{
public:
String( const char * = 0 );
String& operator=(const char*);

private:
int _size;
char *_string;
};

String& String::operator = (const char *pi)
{



cout<<"haha"<<endl;
system("pause");
_size=0;
const char* pt=pi;
while(*pt++)
_size++;
_string=new char[_size+1];
char *str=_string;
while(*str++=*pi++);

return *this;
}

String::String(const char *pi)
{
if(!pi)
{
_size=0;
_string=0;
}
else
{
_size=0;
const char *pt=pi;
while(*pt++)
_size++;

cout<<_size<<endl;

_string=new char[_size + 1];

char *st = _string;

while(*st++ = *pi++);

//delete []_string;
}
}


void main()
{


String ab="hello,the world";
char *c="gogogoog";
ab = c;
}
yunyun1886358 2010-06-28
  • 打赏
  • 举报
回复

String::String(const char *pi)
{
if(!pi)
{
_size=0;
_string=0;
}
else
{
_size=0;
const char *pt=pi;
while(*pt++)
_size++;

cout<<_size<<endl;

_string=new char[_size];

char *st = _string;

while(*st++ = *pi++); // 这一句内存访问越界了,将_string后面一个字节的内存置为了'\0'

delete []_string;
}
}
O湛狼O 2010-06-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 whg01 的回复:]
_string=new char[_size]; 应该是_string=new char[_size+1];要把字符串结束标记计算在内。
char *st = _string; st指向了_string指向的地址,所以delete []_string;这句会导致st指向的内存被释放。
释放之后,就不要再使用了。
[/Quote]

不是这个问题,你试下把while(*st++ = *pi++);这句注释掉,就不会有错!
O湛狼O 2010-06-28
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 pengzhixi 的回复:]
_string=new char[_size];

char *st = _string;

while(*st++ = *pi++);

delete []_string;//你这里就将内存释放了,那后面就不能对_string所指的内存进行操作了。
[/Quote]

不是这个问题,你试下把while(*st++ = *pi++);这句注释掉,就不会有错!
whg01 2010-06-28
  • 打赏
  • 举报
回复
_string=new char[_size]; 应该是_string=new char[_size+1];要把字符串结束标记计算在内。
char *st = _string; st指向了_string指向的地址,所以delete []_string;这句会导致st指向的内存被释放。
释放之后,就不要再使用了。
pengzhixi 2010-06-28
  • 打赏
  • 举报
回复
_string=new char[_size];

char *st = _string;

while(*st++ = *pi++);

delete []_string;//你这里就将内存释放了,那后面就不能对_string所指的内存进行操作了。
经常使用电脑可能也遇到过了! 突然‘咚’的一声 提示 内存不能为read 这个问题我以前也遇到过不知道怎么解决 现在终于有办法了!呵呵! 我们就看看是什么原因引起的吧,另外附送一个小工具修复见下面附件 总结下大概以下9个原因 1、驱动不稳定,与系统不兼容,这最容易出现内存不能为 Read 或者文件保护(主要原因) 2、系统安装了一个或者多个流氓软件,这出现 IE 或者系统崩溃的机会也比较大,也有可能出现文件保护 3、系统加载的程序或者系统正在运行的程序之前有冲突,尤其是部分杀毒软件监控程序 4、系统本身存在漏洞,导致容易受到网络攻击。 5、病毒问题也是主要导致内存不能为 Read、文件保护、Explorer.exe 错误…… 6、如果在玩游戏时候出现内存不能为 Read,则很大可能是显卡驱动不适合(这里的不适合有不适合该游戏、不适合电脑的显卡)也有可能是 系统版本不够新或者不符合该游戏、显卡驱动 7、部分软件本身自身不足的问题 8、电脑硬件过热,也是导致内存不能为 Read 的原因之一。 9、电脑内存与主板兼容性不好也是导致内存不能为 Read 的致命原因! 以上大概就是目前可以引起系统提示 内存不能为read的原因了 另外软件是针对只是针对部分原因引起的内存不为read所做修复,不是100%有效,大家可以试试看 说下原理: 就是批处理使用 regsvr32命令 将动态链接库文件重新注册 (system32下的所有 .dll 和 .ocx 文件;) 注意:由于修复工具会重新注册 system32下的所有 .dll 和 .ocx 文件 此操作对杀毒软件来说属于敏感操作,所以建议使用修复工具的时候,请禁用杀毒软件,以免部分杀毒误报!jie

64,661

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧