1、p 和 "hello,world"存储在内存哪个区域?( )
int main()
{
char *p = "hello,world";
return 0;
}
分析:p在局部变量中,所以p指针变量在栈区(局部变量区),
"hello world"在字符串常量区,即全局区的 ‘. ro段’。
2、一个由C/C++编译的程序,会将占用的内存分为几个部分:堆、栈、代码段、数据段、BSS段。请问以下程序中的变量a、b、c、d,分别被存在内存的哪个部分?
int a = 0;
char *b;
int main()
{
int c;
static char d = 'a';
b = malloc(10);
*b = d;
return 0;
}
分析:
变量a:在全局变量区,已经赋值,故在.data段,即数据段;
指针变量b:在全局变量区,未被赋值,故在.BSS段;
变量c: 在局部变量区,故在栈区;
变量d: 该变量被static修饰,内存分区处于static区,即数据段。
3、如下代码:变量g_iA,g_iB,g_iC,iD,iE, iF, piG,iH 分别在内存中的什么区( ) (H3C)
int g_iA = 1;
int g_iB;
static int g_iC = 1;
void func1(){
static int iD=2;
iD++;
int iE=2;
iE++;
}
void func2(){
int iF=3;
int *piG = (int*) malloc(4);
}
int main(){
int iH = 100;
}
分析:
变量g_iA,在全局变量区,已被赋值,故在 .data区;
变量g_iB,在全局变量区,未被赋值,故在 .BSS区;
变量g_iC,被static 修饰且被赋值,故在static区的 .data区。
变量iD,被static修饰且被赋值,故在static区的 .data区。
变量iE, 在局部变量区,即在栈区;
变量iF, 在局部变量区,即在栈区;
变量piG, 手动分配变量piG的内存空间,故piG在堆区;
变量iH,在局部变量区,即在栈区;
4、有关内存的思考题
void GetMemory(char *p)
{
p =(char *)malloc(100);
}
void Test(void)
{
char *str=NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
}
a、请问运行 Test 函数会有什么样的结果?
分析:
运行Test函数,首先该函数为无参无返回值得函数,运行起来会将栈区中的指针指向堆区10空间的位置,最后将字符串常量区的“hello world”拷贝进去 *str中,最后通过printf函数在屏幕出显示出‘hello world’。
char * GetMemory(void)
{
char p1[] = "hello world"; //char *p = "hello world"
return p1;
}
Void Test(void)
{
char *str=NULL;
str = GetMemory();
printf(str);
}
b、请问运行 Test 函数会有什么样的结果?
分析:
Test函数,首先该函数为无参无返回值得函数,GetMemory是一个无参有返回值是字符指针的函数。运行函数Test函数,会将指针str指向一串字符串常量,最后在屏幕上显示
"hello world"
void GetMemory(char **p,int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello world");
printf(str);
}
c、请问运行 Test 函数会有什么样的结果?
分析:
首先该Test函数为无参无返回值得函数,运行Test函数会将栈区中的指针指向堆区100空间的位置,最后将字符串常量区的“hello world”拷贝进去 *str中,最后通过printf函数在屏幕出显示出‘hello world’。
void Test (void)
{
char *str = (char *)malloc(100);
strcpy(str,"hello");
free(str);
if(str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
d、请问运行 Test 函数会有什么样的结果?
分析:
运行Test函数,首先该函数为无参无返回值得函数,首先在堆区申请100byte的空间,让指针str指向 堆区的该100空间,将hello拷贝进100空间中,然后释放堆区内存,继续运行会导致程序崩坏,造成不可预料的后果。
5、堆和栈的区别是什么?
答案:
内存分配:
栈:内存分配是自动的,且分配和释放速度较快。
堆:内存分配是手动的,通常用于动态分配内存。程序员可以在运行时请求任意大小的内存,使用
malloc
、calloc
、new
等函数进行分配,使用free
或delete
进行释放。存储内容:
栈:存储局部变量、函数参数和返回地址。栈的结构是后进先出(LIFO),即最后分配的内存最先释放。地址是由上至下储存;
堆:存储动态分配的对象和数据,生命周期由程序员控制。堆的结构是无序的,内存块可以在任何时间被分配和释放。地址是由下至上储存;
生命周期:
栈:变量的生命周期与其作用域相关,当函数返回时,栈上的变量会自动释放。
堆:变量的生命周期由程序员管理,直到显式释放内存之前,堆上的变量不会被自动释放。
大小限制:
栈:通常较小,受限于操作系统的设置,栈溢出(stack overflow)会导致程序崩溃。
堆:通常较大,受限于系统的可用内存,堆溢出(heap overflow)也会导致程序崩溃。
访问速度:
栈:由于其结构简单,访问速度较快。
堆:由于需要管理内存分配和释放,访问速度相对较慢。
6、什么是内存泄漏?面对内存泄漏和指针越界,你有哪些方法?
内存泄漏
定义:内存泄漏是指程序在动态分配内存后,没有正确释放这些内存,导致这些内存块无法再被使用,从而造成可用内存逐渐减少,最终可能导致程序崩溃或系统性能下降。
指针越界
定义:指针越界是指程序试图访问未分配或已释放的内存区域,或者访问超出数组边界的内存。这种行为会导致未定义行为,可能引发程序崩溃或数据损坏。
应对方法
对于内存泄漏:
手动管理内存:
确保每次
malloc
、calloc
或new
后都有相应的free
或delete释放堆上的空间
。在释放内存后,将指针设置为
NULL(使指针滞空)
。对于指针越界:
每次使用指针要给它赋值或置空;