c/c++内存机制(转)
Posted 风狼啸天
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c/c++内存机制(转)相关的知识,希望对你有一定的参考价值。
例子(二)
看下面的一小段代码,体会堆与栈的区别:
int foo()
{
//其余代码
int *p = new int[5];
//其余代码
return 0;
}
其中的语句int *p = new int[5];就包含了堆与栈。其中new关键字分配了一块堆内存,而指针p本身所占得内存为栈内存(一般4个字节表示地址)。这句话的意思是在栈内存中存放了一个指向一块堆内存的指针p。在程序中先确定在堆中分配内存的大小,然后调用new关键字分配内存,最后返回这块内存首址,放入栈中。汇编代码为:
int foo()
{
008C1520 push ebp
008C1521 mov ebp,esp
008C1523 sub esp,0D8h
008C1529 push ebx
008C152A push esi
008C152B push edi
008C152C lea edi,[ebp-0D8h]
008C1532 mov ecx,36h
008C1537 mov eax,0CCCCCCCCh
008C153C rep stos dword ptr es:[edi]
int *p = new int[5];
008C153E push 14h
008C1540 call operator new[] (8C1258h)
008C1545 add esp,4
008C1548 mov dword ptr [ebp-0D4h],eax
008C154E mov eax,dword ptr [ebp-0D4h]
008C1554 mov dword ptr [p],eax
return 0;
008C1557 xor eax,eax
}
008C1559 pop edi
008C155A pop esi
008C155B pop ebx
008C155C add esp,0D8h
008C1562 cmp ebp,esp
008C1564 call @ILT+395(__RTC_CheckEsp) (8C1190h)
008C1569 mov esp,ebp
008C156B pop ebp
008C156C ret
如果需要释放内存,这里我们需要使用delete[] p,告诉编译器,我要删除的是一个数组。
例子(三)
看下面的一小段代码,试着找出其中的错误:
#include <iostream>
using namespace std;
int main()
{
char a[] = "Hello"; // 分配在栈上
a[0] = ‘X‘;
cout << a << endl;
char *p = "World"; // 分配在字符串常量存储区的地址
p[0] = ‘X‘;
cout << p << endl;
return 0;
}
发现问题了吗?是的,字符数组a的容量是6个字符,其内容为"hello\0"。a的内容时可以改变的,比如a[0]=‘X‘,因为其是在栈上分配的,也就是在运行时确定的内容。但是指针p指向的字符串"world"分配在字符串常量存储区,内容为"world\0",常量字符串的内容时不可以修改的。从语法上来说,编译器并不觉得语句p[0]=‘X‘有什么问题,但是在运行时则会出现"access violation"非法内存访问的问题。
以下几个函数的变化要看清楚了:
char *GetString1(void)
{
char p[] = "hello,world"; //结果:h。由于数组指针指向第一元素的地址,所以调用之后是h
return p;
}
char *GetString2(void)
{
char *p = "hello,world"; //结果:hello,world。由于p指向“hello,world”字符串常量区域地址
return p;
}
char *GetString3(void)
{
char *p = (char *)malloc(20); // 指向p所分配的堆上的内存空间。
return p;
}
char *GetString4(void)
{
char *p = new char[20]; // 指向p所分配的内存空间,p本身在栈上的,p所指向的空间是堆上的。
return p;
}
附录:内存管理注意事项
【规则1】用malloc或new申请内存之后,应该立即检查指针值是否为NULL,防止使用指针值为NULL的内存,可以在函数入口处断言检测。
【规则2】不要忘记为数组或动态内存赋初值(比如calloc比malloc就要好),指针初始化为NULL(c++中为0)。
【规则3】避免数组或指针下标越界,特别当心发生“多1”或者"少1"的操作。
【规则4】动态内存的申请和释放必须配对,防止内存泄露,具体为malloc/calloc/realloc和free配对,new和delete以及delete[]配对。
【规则5】用free或者delete释放内存后,应立即将指针设置为NULL(C++中为0),防止产生“野指针”、"悬垂指针"。
【规则6】遇到不懂得问题及时debug,一般的虫子debug一下就灰飞烟灭了,一切bug都是浮云而已。
!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->!--CRLF-->以上是关于c/c++内存机制(转)的主要内容,如果未能解决你的问题,请参考以下文章