I*******e 发帖数: 1879 | 1 ☆─────────────────────────────────────☆
everid (everid) 于 (Fri Apr 10 20:46:33 2009) 提到:
写一个class,里面会经常有动态的内存分配,destructor 里用不用把所有动态分配的
内存都释放掉?
比如:
class dynamic{
double* _dp;
public:
dynamic(int size){
_dp=new double[size];
}
~dynamic(){
if(_dp){ delete [ ] _dp; _dp=0;}//这个有必要吗?
}
};
前提是已知没有内存泄漏的情况,直到对象被销毁,destructor里的delete 有没有必
要?
谢谢。
☆─────────────────────────────────────☆
lift (lift) 于 (Fri Apr 10 21:01:00 2009) 提到:
要是外部引用了_dp,对象析构后岂不无效
如果程序不是长时间运行且内存占用不多,没必要释放, |
|
|
p***o 发帖数: 1252 | 3 异常处理的目的不是处理异常,而是管理资源的生存期,以及更广泛地说对象的一致性。
生存期的话,用析构函数就好,和finally有些类似。一致性就不是这里三言两语能说
清楚的了。 |
|
p***o 发帖数: 1252 | 4 catch里可以往外抛异常把。
对于析构函数,stack unwinding的时候出异常的话,程序直接就结束了。 |
|
l**t 发帖数: 64 | 5 这里的placement new的作用就是调用构造函数
实现很简单,是new的另一种形式
void* operator new (size_t, void* p)
{
return p;
}
甚至可以这样写
T t;
t.~T(); //把该对象析构掉
new (&t) T; //重新原地生成新对象,即再次调用构造函数
通常类的赋值操作函数可利用这个来偷懒 |
|
X****r 发帖数: 3557 | 6 哦,我知道你的意思了。你手动加上base::base()的话,base的constructor就不是
implicitly declared的了,以至于derived::derived()虽然是implicitly
declared(而且是implicitly defined),但是non-trivial的了,因为
base::base()现在是non-trivial的。
以下是我的推测:对于non-trivial的derived::derived(),它必须能够access
base::~base()。因为当出现exception的时候,如果derived里的base这个子对象
已经被构建了的话,将会被析构(stack unwinding),所以需要调用base::~base()。 |
|
h*****0 发帖数: 4889 | 7 i see, 因为没有copy constructor,所以直接拷贝了一份指针。但临时变量析构时把
指针对应内容给delete掉了,所以再用就挂了。 |
|
h*******u 发帖数: 15326 | 8 实在没搞明白stl这些container为什么就不给个virtual析构函数,
有时候如果能继承stl容器真是方便多了 |
|
X****r 发帖数: 3557 | 9 我没有理解你的意思,所以不知道你有没有理解我的意思。
我说的是第一题里, std::string没有虚析构函数,所以delete s的时候,
严格地说是undefined behavior,虽然现实中往往就只是内存泄漏。 |
|
X****r 发帖数: 3557 | 10 如果你问的是堆上分配的内存和栈上占用的内存那个存取更快的话,那就和具体的体系
结构有关了,一般来说差别不大。对于具体的程序需要注意的主要是缓存的局域性问题。
选择用堆还是栈有许多因素,目前我能想到的有:数据的生存期;数据的大小;分配的
效率。
delete和free的主要区别在前者还调用对象的析构函数。其实你并无选择啊,new得
到的就必须用delete,malloc/calloc得到的就必须用free。 |
|
z****e 发帖数: 2024 | 11 不需要delete a, ~A(){}时候,vector自动化解。
你这个每次都push一下,的确比较慢。
事先reserve()比较好。 |
|
s*****g 发帖数: 5159 | 12 如果我不delete &a的话,~A(){}什么时候被调用呢? |
|
|
|
|
|
s*****g 发帖数: 5159 | 17 这个回答比较哲学。我可不可以这么理解,退出for循环的时候就应该释放,但是如果
内存管理知道还有
大量的物理内存可用,就延缓释放,直到程序结束或者内存不够的时候在释放? |
|
S**I 发帖数: 15689 | 18 你这说的是garbage collection,C++里没这个。 |
|
r****t 发帖数: 10904 | 19 destroy objects != freeing memory to OS. Runtime can hold onto the
memory of it sees necessary. |
|
h****8 发帖数: 599 | 20 每次for 循环体执行完一次,就释放。因为Local temp生命期结束了
你这个A又不是分配在堆上的 |
|
z****e 发帖数: 2024 | 21 楼主以前用java吗?
我是完全不会java。
楼主java到什么境界了? |
|
s*****g 发帖数: 5159 | 22 看了这个加上其他大牛回答我就明白了。
曾经编过一个指数空间程序,内存占用应该是从2^1逐步升到2^n在逐步降回2^1,但是
在资源监测程序
ganglia看到的是从2^1升到2^n然后保持在2^n,最后程序结束的时候一并收回,就是这
种情况。
这也就是为什么我要问内存确切什么时候回收。我再去仔细查查我的程序。我的程序是
个weak
polynomial time and space算法。 |
|
|
z****e 发帖数: 2024 | 24 "这些年做算法研究一下落伍了"
太搞了吧?这站在科研最前线都叫落伍了? |
|
s*****g 发帖数: 5159 | 25 应该说我落伍了,和算法无关。
老板要求严格测量算法实际的执行时间,所以一直只用数组、指针、malloc、free。我
做的组合问题这
些就够用了,就一直没学STL。现在发现不行了。 |
|
B*******g 发帖数: 1593 | 26 好像STL有些container分配内存是chunk by chunk的 比如一开始1000 bytes, 你需要
地1001
byte的话就再分配1000 b 总共2000 bytes..你即使pop了,内存地址指向的数据变得无
效,但是
系统认为你可能会再用到这部分空间,所以并不回收内存;动态分配内存的cost很高 |
|
z***e 发帖数: 5393 | 27 我比较怀疑,这又不是java/.NET,OS自己可以对memory有算法优化,毕竟也就是page
allocation问题,但是如果你“监测”到内存始终在2^n,那绝对是内存没释放。
当然,也可能是C++那些allocator的原因。如果是C,free了就free了。
程序结束时肯定全部收回,你靠这个判断是不对的。 |
|
s*****g 发帖数: 5159 | 28 我用的是new和delete,不是malloc和free,编译器是g++ 4.xx,操作系统是CentOS 5.
3 x64。
内存的确是释放了,我反复查过了,内存也不是始终在2^N,整个程序执行大概40分钟
,再最后还有2分钟
的时候,这2^n的内存释放了大概 1/2,最后结束的时候全部释放。
见图。
page |
|
|
t****t 发帖数: 6806 | 30 new/delete和malloc/free在OS看来没区别.
5. |
|
z***e 发帖数: 5393 | 31 难道说free之后那块内存还实际上没被free?我知道OS会mark那块内存放个标志什么的
,不见得会立刻放到available可以立刻alloc的内存里面去,等到某个时候再处理。但
是这块内存并不是还在"in use"啊。
打个比方,debug的话, delete了一个pointer,那块部分就标成了FFFFFF之类的东西表
示已经不可用了,这部分显然不会马上分配给其他new/malloc,但是也不算仍然占用的
吧?
老大,有空解释一下吧。 |
|
t****t 发帖数: 6806 | 32 there are 2 levels of "allocation": allocation within the process, aka
memory/heap management, corresponding to section 3 of man pages; and
allocation from the OS, aka data segment size increase/decrease and memory
mapping, corresponding to section 2 of man pages.
the first part is a direct mapping of libc API: malloc()-allocate, free()-
release. If in the process of malloc, the heap runs out of space, or some
other condition triggers, the libc will invoke the 2nd part automatically.
this depend |
|
s*****g 发帖数: 5159 | 33 前辈是南开电子的?
memory
free()-
some
automatically.
free(),
on |
|
|
s*****g 发帖数: 5159 | 35 我看到你签名档里的“多隆”就想起了一个古老的社团。
看来多隆是个常见词。
t |
|
z***e 发帖数: 5393 | 36 ok, got it. thanks.
i think that's why Windows also has APIs like VirtualAlloc and other
confusing calls :) |
|
z****n 发帖数: 1379 | 37 只有析构函数是这样吧?
构造函数还是两个都调用的吧
is |
|
B*******g 发帖数: 1593 | 38 考 我越来越confused了
先问问general map::erase
Erase elements
Removes from the map container either a single element or a range of
elements ([first,last)).
This effectively reduces the container size by the number of elements
removed, calling each element's destructor.
如果我是map map::erase() 不会delete 吧? 文中的意思是map会析构
A?
~Foo() 运行了几次?
Solaris
pointer'
ref
triggered |
|
d****p 发帖数: 685 | 39 |
|
z****e 发帖数: 2024 | 40 smart pointer 不是 绝对不是 永远不是 pointer!
smart pointer 就一user defined class 对象而已。
pointer 里边只有机器地址,没有dtor。
而smart pointer 有dtor。
析构 |
|
z****e 发帖数: 2024 | 41 我觉得呀,这个题目就是递归delete问题。
我的第一个例子,是普通指针,递归delete会产生重复delete问题非零指针。(置零无法解决。)
我的第二个例子,是用户类型,递归delete会产生递归析构问题。(同样置零无法解决。)
而你的答案,和我的答案的本质区别,就是,你认为是“重复delete”,但是我认为不是“重复”,而是“递归”。
你说的“重复”,是可以用置零的办法解决的。但是递归呢,就不行。
所以,我觉得我第二个例子,自己调用自己dtor那个,
应该就是你这个题目的答案了吧?
第一个例子的精神思想是对的,但是也不能算全错吧?
所以我觉得我那个第7楼的回答,里边的精神仍然闪闪发光啊!
你当时把我一棒子打死啊!
你给说说看。啊?
最后,当ref=0,Foo被销毁的时候,同一个shared_ptr对象,要以递归形式,两次进入自己的dtor。
你觉得这个说法如何? |
|
z****e 发帖数: 2024 | 42 俺说的,就是在析构Foo的时候,也就是ref=0,同一个shared_ptr要以递归形式,两次进入自己的dtor。
这两次,都会发现ref=0,然后delete,故而crash???
这个题目的报错,好像和如下代码是一样的。
{
type* p=new type();
shared_ptr sp1(p);
shared_ptr sp2(p);
} |
|
p***o 发帖数: 1252 | 43 ~Foo()的问题在于它造成了 同一个 shared_ptr对象被析构了两次。
当然不用shared_ptr也可以造成这个错误:
#include
struct A;
std::map g;
bool out_of_main = false;
struct A
{
~A()
{
if (out_of_main)
g.erase(0);
}
}; // A
int main(int argc, char* argv[])
{
{
g[0] = A();
}
out_of_main = true;
return 0;
}
我的VC2008直接就stack overflow了。 |
|
z****e 发帖数: 2024 | 44 而且,令我感到更弱智的事情,是在shared_ptr.hpp里边,居然没看见析构函数??? |
|
X****r 发帖数: 3557 | 45 粗看一眼不怎么样啊。
比如这个
cout<<"underflow"<
exit(1);
也太夸张了,哪有这样的。
还有如果你写
Stack s;
析构的时候不会出问题吗? |
|
z****e 发帖数: 2024 | 46 vector 要求要可以拷贝,你没有定义拷贝构造函数,而恰恰是因为这个错误,编译器
自动生成的浅拷贝,被析构的时候,delete了。然后再次被delete,是重复delete问题。
你要避免这个错误,就要写一个深拷贝的拷贝构造函数。 |
|
e******0 发帖数: 211 | 47 在看c++ faq++,有个问题
faq 31.04
#include
#include
using namespace std;
class X { };
void mayThrow() throw(int)
{ throw 42; }
class Fred {
public:
Fred() throw(bad_alloc, int);
~Fred() throw();
Fred(const Fred& f) throw();
Fred& operator= (const Fred& f) throw();
private:
X* p_;
};
Fred::Fred() throw(bad_alloc, int)
: p_(new X()) { mayThrow(); }
Fred::~Fred() throw()
{ cout << "Not reached #1\n"; delete p_; }
int main()
{
try {
Fred f;
cout << "Not reached #2\n... 阅读全帖 |
|
e******0 发帖数: 211 | 48 函数传值 sample x,
形参和实参指向同一地址,
调用函数结束后,调用x的析构函数
所以实参所指的数据也被删除 |
|
e******0 发帖数: 211 | 49 函数传值 sample x,
形参和实参指向同一地址,
调用函数结束后,调用x的析构函数
所以实参所指的数据也被删除 |
|
x****u 发帖数: 44466 | 50 如果是作unit test的话,应该生成一个空白的工程,然后注册这个组件后调用。
用cpputest来对其中每个class做unit test。对这个project不是很了解,主要是对
windows的用visual studio开发的东西不熟,文档也没有,开发的人也走了。
DllCanUnloadNow,DllRegisterServer,DllUnregisterServer这4个函数。这个dll本
身好像是给别的ocx控件提供服务的。
加了一个configuration用来编译成win32 console。在test.cpp的main中调用
afxwininit来支持mfc。试着做了一个简单的cpputest测试例来测试其中的某一个class
,编译和跑测试例本身好像没问题。
析构函数并不出错。这样我就怀疑是不是我新加的configuration弄错了,或者是别的
什么。 |
|