详解动态内存管理(二)

简介: 详解动态内存管理

4. 几个经典的笔试题


4.1 题目1:


void GetMemory(char *p)     
{
  p = (char *)malloc(100);   
}
void Test(void)
{
  char *str = NULL;
  GetMemory(str);   
  strcpy(str, "hello world");
  printf(str);   //注意,该行代码没有错误!解析会讲
}

输出:


42ffa855fc63489f9950c59314734ab5.png


解析:


void GetMemory(char *p)    //用形参 p 接收 str 
{
  p = (char *)malloc(100);    //将动态开辟的内存首地址传给指针变量 p ,并没有传给 str
}
void Test(void)
{
  char *str = NULL;
  GetMemory(str);      //函数调用结束后,str 还是空指针
  strcpy(str, "hello world");    //无法将该字符串复制到空指针内
  printf(str);
}


为什么可以这样写:


printf(str);


我们先来看看 printf 函数的原型:


int printf ( const char * format, ... );


将格式所指向的 C 字符串写入标准输出(标准输出)。如果 format 包含格式说明符(以 % 开头的子序列),则格式后面的其他参数将被格式化并插入到结果字符串中,以替换它们各自的说明符。


还记得我们之前接触的 printf 的写法有:


printf("hello world");


之所以能打印出来,是因为我们将字符串的首元素 ‘h’ 的地址传入了 printf 函数中,那么我们直接传字符串的首元素地址 str 也是一样的


4.2 题目2:


char *GetMemory(void)
{
  char p[] = "hello world";
  return p;
}
void Test(void)
{
  char *str = NULL;
  str = GetMemory();
  printf(str);
}

输出:


07786f668a9543a29bbd6e5cdb09251b.png


解析:


char *GetMemory(void)
{
  char p[] = "hello world";
  return p;   //指针p指向了字符‘h’,
}             
void Test(void)
{
  char *str = NULL;
  str = GetMemory();  //接收指针p的值,但当该函数调用结束后,局部变量 p 所指向的内容就被销毁了
  printf(str);        //所以打印出来就是乱码
}


4.3 题目3:


void GetMemory(char **p, int num)
{
  *p = (char *)malloc(num);
}
void Test(void)
{
  char *str = NULL;
  GetMemory(&str, 100);
  strcpy(str, "hello");
  printf(str);
}


输出:


7fb7b258198c42079832d68aca5ffa83.png


咋一看,似乎没啥问题,虽然输出没问题,但是我们开辟的动态内存没有进行释放,导致了内存泄漏,这虽然不影响结果,但也是很严重对问题。


4.4 题目4:


void Test(void)
{
  char* str = (char*)malloc(100);
  strcpy(str, "hello");
  free(str);
  if (str != NULL)
  {
  strcpy(str, "world");
  printf(str);
  }
}


输出:


870e91bf84494ab1b730a637fab0b494.png


输出没有问题,我们看下面的警告,因为本题没有判断 str 是否为空,所以在复制字符串的时候警告,当 free 完后,那块动态内存开辟的空间就不属于我了,str 就是野指针了,再进行访问就是非法访问。

我们可以对其进行修改一下:


void Test(void)
{
  char* str = (char*)malloc(100);
  if(str == NULL)     //判断是否为空指针
  return 1;
  strcpy(str, "hello");
  free(str);
  str = NULL;  //养成习惯,free 后就置空,防止野指针
  if (str != NULL)     //这样就不会再出错了
  {
  strcpy(str, "world");
  printf(str);
  }
}


最后


下期讲解 C/C++ 程序的内存开辟和柔性数组。


相关文章
|
19天前
|
编译器
动态内存管理
动态内存管理
18 0
|
2月前
|
编译器 程序员 C语言
动态内存管理(超详细!)
动态内存管理(超详细!)
27 2
|
6月前
|
C语言 Python
动态内存管理(下)
动态内存管理(下)
29 0
|
2月前
|
程序员 C语言 C++
详解动态内存管理!
详解动态内存管理!
|
5月前
|
编译器
动态内存管理(1)
动态内存管理(1)
36 0
|
5月前
|
程序员 编译器 C语言
动态内存管理总结
动态内存管理总结
38 0
|
5月前
|
程序员 C语言 C++
动态内存管理-2
动态内存管理
21 0
|
5月前
|
程序员 编译器
动态内存管理-1
动态内存管理
33 0
|
6月前
|
C语言 C++
C++中的动态内存管理
C++中的动态内存管理
|
6月前
|
C语言
动态内存管理(上)
动态内存管理(上)
23 0