从哪里来的两个 delete ?

SENDFREE 2002-02-19 08:24:04
下面的程序重载了 delete 运算,
我的main中没有任何的语句, 输出结果表明 delete 被调用了2次,
请教各位c++高手, 这两个delete 都是程序在什么时候调用的,
重载new,但是new一次也没有被调用, 为什么?

#include <iostream.h>
#include <alloc.h>

void operator delete (void * loc)
{
cout <<"\n In my delete\n";
free(loc);
return ;
}

void * operator new (size_t size)
{
cout <<"\n In my new\n";
return malloc(size);
}

void main()
{}
...全文
49 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
LLnju 2002-02-21
  • 打赏
  • 举报
回复
上面的代码在 <ios> 中。
LLnju 2002-02-21
  • 打赏
  • 举报
回复
>>看来delete是在程序结束的时候调用的

当然如此,cout 是全局变量,在 main 运行前构造,main 结束后再析构。其实如果你用 VC 可以看到是在 mainCRTStartup 中调用的,调用我们的 main 的就是它。
LLnju 2002-02-21
  • 打赏
  • 举报
回复
用 std::cout 时候可以看到,以前的不标准的实现不是这样的。你可能用了 #include <iostream.h> 吧,改一下就有了。用老的一套好像没有
purples 2002-02-20
  • 打赏
  • 举报
回复
to SENDFREE (菜鸟先飞)
3、cout 不执行 new/delete 函数。
如果执行的话肯定会出现循环导致死机,事实上没有死机。
错!
不信你用printf()!它不调用new,delete,再看看结局!
我是对的。
c++是一个正在更新的语言,tc30与当今标准之间有极大的差距,你用他怎么学好c++呢?还是换一个先进的编译器吧。
注:cout派生自iostream类
LLnju 2002-02-20
  • 打赏
  • 举报
回复
free(_Fv); //!****** 调用了 operator new
改成 free(_Fv); //!****** 调用了 operator delete 哈哈
LLnju 2002-02-20
  • 打赏
  • 举报
回复
跟踪程序的运行,可以看到两次的 delete 调用是由于 cout 的析构函数调用的,也算你运气,程序中 cout 实际上是用被重载前的 new 分配的内存,却用你重载的 delete 释放内存,所以前面的有些人遇到了非法操作就不奇怪了。如果你再用用 cin ,就可以发现 调用了 4 次 delete。
还有你在 new 中调用 cout << ... 显然非法的, cout 将调用 new 分配内存,这个时候 cout 还无效呢,结果显然是没有定义的。所以我把这两句删了,在函数中设置断点。并在 main 中调用 cout.operator <<

把 #include <iostream.h> 改成 #include <iostream> , 改 cout 为 std::cout , 可以看到 new , delete 被调用情况:


locale::_Locimp *__cdecl locale::_Init()
{ // setup _Global and "C" locales
_Lockit _Lk;
if (_Locimp::_Global == 0)
{ // create new locales
_Locimp::_Global = new _Locimp; //!******
atexit(&_Tidy);
_Locimp::_Global->_Cat = all;
_Locimp::_Global->_Name = "C";
_Locimp::_Clocptr = _Locimp::_Global;
_Locimp::_Clocptr->_Incref();
new (&classic_locale) locale(_Locimp::_Clocptr);
}
return (_Locimp::_Global);
}

void _Copy(size_type _N)
{size_type _Ns = _N | _MIN_SIZE;
if (max_size() < _Ns)
_Ns = _N;
_E *_S;
_TRY_BEGIN
_S = allocator.allocate(_Ns + 2, (void *)0); //!****** 调用了 operator new
_CATCH_ALL
_Ns = _N;
_S = allocator.allocate(_Ns + 2, (void *)0);
_CATCH_END
if (0 < _Len)
_Tr::copy(_S + 1, _Ptr,_Len>_Ns?_Ns:_Len);
size_type _Olen = _Len;
_Tidy(true);
_Ptr = _S + 1;
_Refcnt(_Ptr) = 0;
_Res = _Ns;
_Eos(_Olen>_Ns?_Ns:_Olen); }


locale::_Locimp::~_Locimp()
{ // destruct a _Locimp
_Lockit _Lk;
for (size_t _N = _Nfv; 0 < _N; )
if (_Fv[--_N] != 0)
delete _Fv[_N]->_Decref();
free(_Fv); //!****** 调用了 operator new
}

void __cdecl locale::_Tidy()
{ // discard _Global locale
_Lockit _Lk;
if (_Locimp::_Global != 0)
delete _Locimp::_Global->_Decref(); //!****
}

上面的程序是在 VC 中的情况
SENDFREE 2002-02-20
  • 打赏
  • 举报
回复
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

void operator delete (void * loc)
{

printf("p");
std::cout <<"c";
free(loc);
return ;
}

void main()
{
std::cout<<"main";
}

output:
mainpp


看来delete是在程序结束的时候调用的,
调用以前std::cout已经不起作用了,(是不是程序结束部分搞的?)

to LLnju(LLnju): 你的代码从哪里搞的,我怎么没有trace到,眼都花了.
这个locale是什么东西?
SENDFREE 2002-02-20
  • 打赏
  • 举报
回复
purples<- new 的内存我想应该放在 MCB 中,不然delete怎会知道
这块内存的大小.
blaise 2002-02-20
  • 打赏
  • 举报
回复
if u use vc, u can see the call stack when crash.The caller is DOExist. The problem is not why delete get called, but try to use cout<< after it get destructed
purples 2002-02-20
  • 打赏
  • 举报
回复
cout->new(new被重载)->cout(在new()中调用)->new.....)
purples 2002-02-20
  • 打赏
  • 举报
回复
cout->new(new被重载)->cout(在new()中调用)->new.....
cnss 2002-02-20
  • 打赏
  • 举报
回复
当然,自己不能控制栈的分配,是编译器改变ESP,EBP
cnss 2002-02-20
  • 打赏
  • 举报
回复
to purples():
我没说在栈里啊,在栈里分配东西只改变ESP,EBP就好了,哪儿用的着调用乱七八糟的函数啊 ^&^
LLnju 2002-02-20
  • 打赏
  • 举报
回复
cout 构造函数调用了 operator new , 析构调用了 operator delete ,这个不用怀疑。
to purples: cout 调用 new 为什么出现循环,能给个理由吗?好像不对吧。
SENDFREE 2002-02-20
  • 打赏
  • 举报
回复
我想,重载delete是否当机与系统和编译器都有关系,与程序也有一点点关系。
至于 delete 怎么来的实在没有多大的价值。

心得如下:
1、delete 是在程序退出的时候被调用的,调用几次与编译器有关:
TC30调用了6次, VC6不明,但至少调用了2次。

2、TC30中delete 调用了6次,cout 却执行了2次,说明
delete执行2次后程序的cout代码已经被free掉了,所以没有执行。(好危险)
计数部分是asm,仍然可以执行。
证明:在显示字符后加入按任意键继续的代码

mov ax,0
int 16h
然后可以看到,头两次按键前都会出现 cout出来的 in my delete,而2次以后
就只有左上角字符的变化了。



VC6中cout执行1次后,便出现如下错误:
runtime error R6025
- pure virtual function call
这说明第1次delete就删掉了 cout 代码, 使 cout 不能执行。

3、cout 不执行 new/delete 函数。
如果执行的话肯定会出现循环导致死机,事实上没有死机。


4、用屏幕字符进行计数的程序不好用在VC中,win32控制台程序是32bit的,
不能修改ds,不知道怎么取得显存地址了。

5、程序运行之初,内存需要怎么分配已经在EXE文件头部写好了,由系统自动分配。
程序还没有自己的空间的时候自然也不能调用new函数,
像上面的什么也没有作的程序也没有用到 new.
程序结束的时候要自己释放空间,就像当初DOS程序要调用
mov ah,4ch
int 21h
一样。c++程序复杂一些,用到了自己的delete函数。

cnss说的有点道理。
请指正。
purples 2002-02-19
  • 打赏
  • 举报
回复
to cnss(风) :
不是吧,new在堆中分配空间,不用它则在栈中。
purples 2002-02-19
  • 打赏
  • 举报
回复
bc5.0也不行,程序崩溃。tc30太老了,很多规则都不能正确实现。
答:delete函数被调用了 6 次。
让 cout 起作用后结果仍然表示delete被调用6次,
但是cout 只执行了2次, 有点矛盾哦。
不过证明了cout没有调用delete (理由:有没有它delete 都被调用了6次)

你new有没有改写?new中cout在退出new()时不执行delete吗?
cnss 2002-02-19
  • 打赏
  • 举报
回复
我理解是这样的.
拿VC来说,new里实际调用_nh_malloc,_nh_malloc函数实际调用_nh_malloc_dbg,里面又调用别的.(这些函数均需要前面函数的参数,还有加上自己的参数)最终是操作系统分配的.
,所以VC内部需要分配内存的时候不调用new,直接用那些内部用的函数.
而delete就是直接调用free(void *),然后free里也一级一级的调用函数.
这样的话,free只要提供地址就行(内存大小信息在内存地址前面放着),所以所有的释放都可以用free(或delete).而new就不行了,有的分配需要加入特别的参数,这样一般的new就无能为力.
SENDFREE 2002-02-19
  • 打赏
  • 举报
回复
我只是想知道 C++做的程序运行的时候干吗不调用new分配内存,
却要调用 delete 释放内存, 他不怕我的delete 和他的new不匹配吗?
duqiang2050 2002-02-19
  • 打赏
  • 举报
回复
我vc6运行通过,就改了个库:
这么回事?能解释解释?运行结果是什么也不输出,一切正常。
我开始也不好使(2次),后来不知道怎么改来改去就好使了


#include <iostream.h>
#include <stdlib.h> // ***********改了这里

void operator delete (void * loc)
{
cout <<"\n In my delete\n";
free(loc);
return ;
}

void * operator new (size_t size)
{
cout <<"\n In my new\n";
return malloc(size);
}

void main()
{}
加载更多回复(8)

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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