下面两种做法,哪个比较合理,即指针p频繁赋值的时候,不影响执行速度和内存占用(包括尽可能少的碎片)。
1、
int i;
char * p;
for (i=0;i<65535;i++)
{
p="abcdefg";
p="abcd";
p="ab";
p="abcdefghijk";
}2
int i;
char * p;
p=new char[65535];
for (i=0;i<65535;i++)
{
p="abcdefg";
p="abcd";
p="ab";
p="abcdefghijk";
}
delete p;
1、
int i;
char * p;
for (i=0;i<65535;i++)
{
p="abcdefg";
p="abcd";
p="ab";
p="abcdefghijk";
}2
int i;
char * p;
p=new char[65535];
for (i=0;i<65535;i++)
{
p="abcdefg";
p="abcd";
p="ab";
p="abcdefghijk";
}
delete p;
解决方案 »
- 关于ClassXP的 问题
- 请专家来看看我的程序,帮我修改一下
- 在对话框窗口里显示图片的一个问题,郁闷好几天了。。。
- 讨论一个类似于CLEARDDTS的bug管理程序的可行性,分不够再加
- 如何改变opengl绘图窗口的逻辑坐标,并且显示的让人舒服一点。
- 1000分求费尔防火墙源码
- 为什么出错?数据显示不该这么难吧!!
- 如何将Universal Coordinated Time 转换为System Time???
- 虚拟内存不断减少,用VirtualAlloc()有问题?
- 谁知道YAMAHA 719E-S声卡的驱动程序在哪下?注意:是E-S呦!!!
- ?求助:连续两次运用CTabCtrl,第二次为何无效?
- ADO访问oracle的问题!?
new char[65535]看起来是申请了一大块内存,但我想讨论的是多次赋值的影响
简单说就是
p="abcdefg";
p="abcd";
p="ab";
如果是new了一块空间,那是否无论p如何变化,都保持该空间?
如果第一种方式,那么上面三条执行过后,p占的内存是两个字节(ab),还是14个字节(abcdefg),有没有碎片的产生?
第一种和第二种都没事么?
为什么
第二种是否只在申请的内存范围内操作
第一种内存是怎么申请的?
能否详细解释一下,谢谢!
比如p="aa";
有人说当p="abc"是改变了指针的指向,就是抛弃了原来的地址,指向新地址,而p[0]='a';p[1]='b';p[2]='c';p[3]='\0';才是为指针指向的内容赋值,所以两种方法都有问题
int i;
char * p; //定义指针
p=new char[65535]; //内存动态分配地址给P ,对后面有什么用??
for (i=0;i<65535;i++)
{
p="abcdefg"; //P指向字符串"abcdefg"首地址 指针变量不在指向p=new char[65535]的地址了
p="abcd"; //那么new char[65535]成了真正的碎片了.
p="ab";
p="abcdefghijk";
}
delete p;
测试指针p频繁赋值的时候,不影响执行速度和内存占用(包括尽可能少的碎片)。
我也认为会消耗光内存资源,但实际是下面程序没事,所以不理解
理论上应该消耗光至少65535*65535*36/1024/1024=146451MB(第一个串)内存资源for (i=0;i<65535;i++)
{
for (j=0;j<65535;j++)
{
p="abcdefghijklmnopqrstuvwxyz1234567890";
p="abcd";
p="ab";
p="abcdefghijk";//是不是可认为上面三个都成了碎片?
}
}
delete p;
p="abc"是改变了指针的指向,就是抛弃了原来的地址,指向新地址,我同意这种说法
在你的最后一个帖子中,"abcdefghijklmnopqrstuvwxyz1234567890"占用的是堆栈空间,当第二个for循环一遍后,"abcdefghijklmnopqrstuvwxyz1234567890"会被释放,然后重新分配
您的意思是释放内存?
我最开始认为重新赋值就是释放以前内存,指向新地址,不会产生碎片,但不敢确认,也不敢说new了空间后赋值就不是在该空间操作了尤其大家的答案各不相同,所以也有些认不准了
主要疑问
1、new空间后,执行赋值操作,是否还在new的空间内?
2、多次赋值会不会产生内存碎片?
3、在赋值的时候new空间和直接操作有无区别,是否只要是赋值就不应该new空间?(如果不赋值,不new一个空间p[0]=字符方式是无法执行的)
2、多次赋值(象你程序中的),不会产生碎片
3、你是在给指针赋值,相当于将指针指向了其他的空间,
for (i=0;i<65535;i++)
{
p="abcdefg";
p="abcd";
p="ab";
p="abcdefghijk";
}
之后,p指向的是一个非法空间,无论怎样,这样写程序都是危险的
int i;
char * p;
p=new char[65535];
for (i=0;i<65535;i++)
{
p="abcdefg";
p="abcd";
p="ab";
p="abcdefghijk";
}
delete p;
这种情况下会崩溃
你没有在debug下执行?我执行的时候ASSERT了一个错误啊
{
for (j=0;j<65535;j++)
{
p="abcdefghijklmnopqrstuvwxyz1234567890";
p="abcd";
p="ab";
p="abcdefghijk";//是不是可认为上面三个都成了碎片?
}
}
delete p;"abcdefghijklmnopqrstuvwxyz1234567890";
"abcd";
"ab";
"abcdefghijk";
这些都是作为常量字符串分配在静态空间里面的,怎么会是内存碎片片呢?
/*
类说明:指针测试
*/
class PointerTest
{
private:
char *p;
void DeleteTest();//指针删除函数
public:
void RunTest(); //外部调用函数
};
/*
函数说明:测试删除指针
返回值:无
参数:无
*/
void PointerTest::DeleteTest()
{
int i;
for (i=0;i<65535;i++)
{
p="abcdefghijklmnopqrstuvwxyz1234567890";
p="abcd";
p="ab";
p="abcdefghijk";
}
delete p; //我删了
}
/*
函数说明:调用删除指针函数1000次
返回值:无
参数:无
*/
void PointerTest::RunTest()
{
int i;
for(i=0;i<1000;i++)
DeleteTest();
}外部调用如下:
PointerTest Ptest;
Ptest.RunTest();
或
PointerTest *Ptest;
Ptest=new PointerTest();
Ptest->RunTest();
都没出错或崩溃!!
int i;
char * p; //栈
for (i=0;i<65535;i++)
{
p="abcdefg"; //栈,每次循环自动释放
p="abcd"; //栈,每次循环自动释放
p="ab"; //栈,每次循环自动释放
p="abcdefghijk"; //栈,每次循环自动释放
}2
int i;
char * p; //栈
p=new char[65535]; //堆,一块完全没有用到的内存......
for (i=0;i<65535;i++)
{
p="abcdefg"; //栈,每次循环自动释放,此时失去对new char[65535]的地址,将无法释放
p="abcd"; //栈,每次循环自动释放
p="ab"; //栈,每次循环自动释放
p="abcdefghijk"; //栈,每次循环自动释放
}
delete p; //没有起到释放内存的目的,只是将p的内容失效,堆里面的那块内存铁定要泄露了。
同时栈里还放有局部变量,一旦超出生存周期就会被自动删除。堆是很大的,32位操作系统可以有4G的大小,栈比较小,若果栈溢出,程序很定会出错的,我曾经在研究黑白棋的算法的时候,一个递归调用里,全部用的都是数组,结果把栈给挤满了......栈比堆要快。栈不存在碎片问题,这是由它的数据结构决定的。
堆内频繁使用new/delete会造成大量内存碎片,堆的性能也会下降。
第二种,是吃饱了没事干,分配了堆的空间,delete会泄漏,不一定会崩溃,看你的内存顶不顶得住
只有频繁 分配 然后释放才会产生碎片比如 你先分配10K 然后分配20K然后释放10K。。然后分配10BYTE..
这样系统在后面的分配过程中 如果没有足够用的内存用 就会把那些 零散的内存进行整合 就是合成一块以供后面的使用 这样的效率是非常低的。。所以应该避免这种情况。。你如果分配了一段内存了 表示告诉系统,这块系统我在用,系统就不会跟你抢的,所以你对这段内存多么频繁的写,读,操作都没事。。因为这是不同的概念。。
delete p;//只把栈里的p内容置为失效,堆里的空间没有释放
应该改成
delete [] p;//释放堆里的空间
for (i=0;i<65535;i++)
{
p="abcdefg"; //栈,每次循环自动释放
p="abcd"; //栈,每次循环自动释放
p="ab"; //栈,每次循环自动释放
p="abcdefghijk"; //栈,每次循环自动释放
}
为什么是每次循环自动释放,而不是在p指向下一个串的时候就释放?
如果是指向栈,当delete p的时候意味着p失效,是否意味着栈内存释放了
delete [] p;//释放堆里的空间
p的地址都变了,这个会释放堆里的空间?
to zhoujiamurong(有分俺就不要,俺要知识)
如果按上面的说法,仅是丢失了16K的内存,怎么会崩溃?
不会吧,这么多人都执行了,现在思维混乱中...to beyondtkl(大龙驹<弱水三K, 我取1bit>)
频繁new和delete会降低系统性能这个知道,但现在普遍认为栈比较快
采用第一种方式的时候,应该是自动占用和释放栈中的内存,应该避免?
***************************************************
p="abcdefghijk"; //栈,每次循环自动释放
***************************************************
所以,你在释放栈的空间,栈是系统自己释放的,所以系统还会释放,就有问题了
但我怎么没测试出崩溃?
另外,为什么是每次循环自动释放,而不是指向下一个地址自动释放?
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
***************************************************
p="abcdefghijk"; //栈,每次循环自动释放
***************************************************
p根本不是指向栈的,而是数据区
我突然发现一个问题,
***************************************************
p="abcdefghijk"; //栈,每次循环自动释放
***************************************************
p根本不是指向栈的,而是数据区
*/
是啊,因为p本身就是一个指针啊
class a{}
a b1
a *b2;
b1是栈中的,b2是堆里的,但现在直接赋值指针是指向哪里的?问题结论发展:
1、第一种好,因为第二种new的空间大,即认为第二种在new空间内操作
2、第二种好,因为第二种有内存池,不会产生碎片
3、第二种好,因为第一种是栈分配空间,第二种是堆分配空间
4、第一种和第二种都有问题,因为分配空间无效,直接改变指针地址,会消耗光内存
5、第一种和第二种一样,最后都是在栈分配空间,不会消耗内存,循环时自动回收(为什么循环时回收?),第二种new无作用,有碎片
6、第二种的delete会出错,因为p地址变了
7、第二种的delete不会出错,除非是不停地new空间,消耗光资源
8、第二种的delete会出错,因为不能释放两次
9、栈比堆快,不要用频繁new delete,意思是用第一种好点?如果非要用最好new了就独享
10、指针直接赋值不能这么写?
11、直接赋值不是栈分配空间,是指向数据区的
p根本不是指向栈的,而是数据区
因为p本身就是一个指针啊
应换种问法
其内容需要不停地变成从端口传过来的字符串(需要解密运算,最终返回结果是一个String)
性能最好和并且安全的方法是什么?是让指针指向这个串吗?