C++里,该用delete [] pc;的时候少写了[]会如何?
RT.............
[解决办法]
string *stringArray = new string[100];
...
delete stringArray;
stringArray 指向的100 个string 对象中的99 个不会被正确地摧毁,因为他们的析构函数永远不会被调用。
[解决办法]
导致可怕的内存泄漏.
[解决办法]
内存泄漏
[解决办法]
内存泄漏
当然能继续分配下去了。。。, 但是如果程序不关闭会耗尽系统的内存
[解决办法]
不会怎么样的
这个问题我记得答案是delete和delete[]动作是一样的
[解决办法]
希望朋友们一定要注意,必须要有‘[]’符号用以告诉编译器,指针(此处当然是你的pc)所指向的是数组,因此在释放pc所指向的内存区块时必须要查询和使用该数组的维度信息,这样才能完全释放pc所指的数组占用的内存资源。C++编译器出于效率上的考虑,仅在有‘[]’时,才会查询数组的维度信息。否则,编译器将认为pc指向的是单个内存单元,因而delete掉pc所指向的单个内存单元造成内存资源泄漏。至于有些朋友有意对数组的delete操作不用‘[]’而没有觉得程序的运行有异常,但我要告诉你们: "内存资源确时已经发生了泄漏!!! "
请参考 < <C++ Common Knowledge> > -条款36-page93。
[解决办法]
呵呵,
习惯啊,习惯
所有的坏习惯一定要改,共同借鉴。
[解决办法]
给你做个例子看看:
#include <iostream>
using namespace std;
class foo
{
public:
foo()
{
cout < < "foo created " < < endl;
}
~foo()
{
cout < < "foo deleted " < < endl;
}
};
int main( void )
{
foo *p = new foo[5];
delete p;
return 0;
}
在g++ 下编译通过。
运行:
foo created
foo created
foo created
foo created
foo created
foo deleted
可以看到只一个foo给删除了。
[解决办法]
对象数组本身占用的内存一定会被释放
但是析构函数只调一个
如果对象申请了内存并打算在析构的时候释放就会有问题了
[解决办法]
nevergone() 正解
[解决办法]
int *c=new int[10];
指针c指向的是数组的首地址,
delete没有加[],则只释放c指向的那个地址空间,若加了[]才会释放整个数组空间
[解决办法]
内存泄露是肯定的。也许在pc机器上看不到什么结果。(我猜测是虚拟内存,操作系统优化的原因)
如果做嵌入式开发,比如:手机开发等你会看的很明显的。内存严重泄露。。。(我做过测试的)
至于更详细的东西,还望高人出现。。。。
借用楼上的话(Obsidianhom())
int *c=new int[10];
指针c指向的是数组的首地址,
delete没有加[],则只释放c指向的那个地址空间,若加了[]才会释放整个数组空间
[解决办法]
int *c=new int[10];
delete c;
-------------------------
这个不会产生内存泄露
delete 和 delete[] 的区别只是调几个析构函数, delete 调一个 而 delete[] 调N个
[解决办法]
错误的东西就是错误的,请别期望错误的结果仍然有规律可循.
[解决办法]
还是用C++标准来解决问题:
5.3.5 Delete [expr.delete]
1 The delete-expression operator destroys a most derived object (1.8) or array created by a new-expression.
delete-expression:
::opt delete cast-expression
::opt delete [ ] cast-expression
The first alternative is for non-array objects, and the second is for arrays. The operand shall have a pointer
type, or a class type having a single conversion function (12.3.2) to a pointer type. The result has type
void.
2 If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned
conversion function, and the converted operand is used in place of the original operand for the remainder of
this section. In either alternative, if the value of the operand of delete is the null pointer the operation
has no effect. In the first alternative (delete object), the value of the operand of delete shall be a pointer
to a non-array object or a pointer to a sub-object (1.8) representing a base class of such an object (clause
10). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of
delete shall be the pointer value which resulted from a previous array new-expression.72) If not, the
behavior is undefined.
从上面可以看出,如果该用delete[],但是却用了delete的话,结果是未定义的。未定义的意思就是编译器想怎么做就怎么作。
不过有一点是可以肯定的,那就是delete只会调用一个destructor,而delete[]会调用N个destructor
[解决办法]
to marrco2005: 为什么 "不过有一点是可以肯定的,那就是delete只会调用一个destructor "?
我只看到 "the behavior is undefined "
[解决办法]
delete与delete[]如果用错的话,问题不只是内存泄漏,还很可能出现保护错! 参见:
http://community.csdn.net/Expert/TopicView3.asp?id=5650265
[解决办法]
....marrco2005才是正解~~
10). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of
delete shall be the pointer value which resulted from a previous array new-expression.72) If not, the
behavior is undefined.
[解决办法]
对基本类型来说,vc能自动析构整个数组
比如p = new int【1000】,使用delete p和delete[] p的效果是一样的
[解决办法]
前几天看到一本书中说:delete[]删除的更干净些!
[解决办法]
http://en.wikipedia.org/wiki/Undefined_behavior
Undefined behavior
From Wikipedia, the free encyclopedia
Jump to: navigation, search
In computer science, undefined behavior is a feature of some programming languages — most famously C. In these languages, to simplify the specification and allow some flexibility in implementation, the specification leaves the results of certain operations specifically undefined.
For example, in C the use of any variable before it has been initialized yields undefined behavior, as do division by zero and indexing an array outside of its defined bounds (see Buffer overflow). This specifically frees the compiler to do whatever is easiest or most efficient, should such a program be entered. In general, any behavior whatsoever is valid after a situation resulting in undefined behavior has been encountered. In particular, it is never required that the compiler diagnose undefined behavior — therefore, programs invoking undefined behavior may appear to compile and even run without errors at first, only to fail on another system, or even on another date. When an instance of undefined behavior occurs, so far as the language specification is concerned anything could happen, ranging from a "reasonable " action all the way to a system crash.
On the other hand, in some languages (including C), even the compiler is not bound to behave in a sensible manner once undefined behavior has been invoked. One famous piece of hacker lore is the behavior of version 1.34 of the GCC C compiler when given a program containing the #pragma directive, which has an implementation-defined behavior according to the C standard. (It should be noted here that "implementation-defined " is more restrictive than "undefined ", requiring the implementation to document what it does.) In practice, many C implementations recognize, for example, #pragma once as a rough equivalent of include guards — but GCC, upon finding a #pragma directive, would instead attempt to start Emacs running a simulation of the Towers of Hanoi. Failing that, it would try to launch other commonly distributed Unix games such as NetHack and Rogue.
Under some circumstances there can be specific restrictions on undefined behavior. For example, the instruction set architecture of a CPU might leave the behavior of some forms of an instruction undefined, but if the CPU supports memory protection then the architecture specification will probably include a blanket rule stating that no user-accessible instruction may cause a hole in the operating system 's security; so an implementation of the architecture would be permitted to corrupt all user registers in response to such an instruction but would not be allowed to, for example, switch into supervisor mode.
[解决办法]
大的原则大家都知道,new/delete, new[]/delete[]应该配对使用。具体实现上不同的编译器会有不同的方式,但是这些不同的实现都遵循new/delete,new[]/delete[]的定义:
new分配内存,构造一个对象
new[n]分配内存,构造n个对象
delete析构一个对象,释放内存
delete[]析构n个对象,释放内存
这里面问题最大的就是delete[]如何确定n.理由是要析构n个对象。但是仔细想想,这里的理由并不充分,“析构n个对象”可能什么也不需要做,因为那些trivial destructor的对象是不需要析构的,对于这些对象,delete[]就意味着释放内存。但是释放内存还是会有问题,这个n到底存储在哪里?VC6.0是存储在内存前部32个字节(32bit PC),如果是这种实现方式,那么真真需要释放的内存不是传给delete[]的指针,而需要前移4byte,更要命的是delete[]不知道这个n到底是不是真正存在(也就是说他不知道这块内存是new出来的还是new[]出来的,或者是随便哪里找来的指针),他能用来作为判断的依据的只有这个指针的类型,所以一种实现方式是:如果这种类型的对象需要有n的存在,那么就从指针的前4byte取出n,然后操作;另外一种实现方式是不管这个指针的类型,直接认为有n的存在。VC6.0是采用第一种方式。
显然,这个new[]需要存储这个n的,理由是delete[]需要确定这个n,但是这个理由也不充分,delete[]可能不需要确定这个n,如上面的讨论。对于new[]来说,他也只知道所要分配内存的类型,一种可行的方案是根据类型来确定是否要存储n,另一种方案是不管什么类型都把n存下来。VC6.0是采用第一种方式。
最后总结一下vc6.0的实现方式,VC6.0尽量减少n的存在,假设类型T
1.如果T是POD,那么new == new[], delete == delete[]
2.如果T没有non-trivial destructor, 那么delete == delete[]
3.如果T没有non-trivial constructor且没有non-trivial destructor, 那么new == new[] delete == delete[].
4.如果T有non-trivial destructor那么delete[] pT在释放内存的时候调用的是free(void*((UInt32)pT - 4)),这时候如果混用delete[]/delete new/new[]则会出现明显问题
这些是我以前在VC6.0上做出的实验得出的结论,并且“对于自已那些简陋的所谓的测试似乎颇为自信”:),之所以作这样的实验,是为了确定为什么在VC6.0下有时候混用delete[]/delete new/new[]没有出问题。
不同的编译器会有不同的实现方式,我一直觉得将new视作new[1],将delete视作delete[],无论什么时候都存储n,是最安全的实现方式,虽然会浪费很多空间。
总而言之,new/delete new[]/delete[]应该配对使用,或许现在在VC6.0上编译的代码可以正常运行,但说不定哪天这断代码会被其他的编译器编译而导致运行错误。
[解决办法]
int* n = new int[100];
delete[] n; 1)
delete n; 2)
1) 2) 都会把整个区域释放,不同的在于 2)只调用了首元素的析够,而 1) 调用全部元素
的析构,不单是这样,基于不同的编译器,保存元素个数的地方不一样,1)在内部调用free的时候可以会把数据地址偏移
[解决办法]
那么你delete的就只是个指针而不是数组空间了