栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

动态内存分配

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

动态内存分配

 1.malloc与free成对使用:malloc函数在内存空间申请空间,但不初始化,函数申明为void* malloc(size_t size)  一般需要强制类型转换。开辟的空间的首地址用指针变量存放,以便找到。空间的释放free(指针变量),释放空间后把空间里面的数据清空,但是指针变量里面还是存放的这块空间的首地址。后续若再次使用到该指针变量将会很危险,所以最好还是把该指针变量置空。

 

#include
#include
#include
#include

int main()
{
  int* p=(int*)malloc(10*sizeof(int));
  // 开辟不成功,打印不成功原因
  if(p==NULL)
   {
     printf("%sn",strerror(errno));
   }
  else
   {
     // 开辟成功,使用空间
     int i=0;
     for(i=0;i<10;i++)
      {
        *(p+i)=i;//依次为该空间赋值。
      }
     for(i=0;i<10;i++)
      {
        printf("%d",*(p+i));
      }
   }
  free(p);
  p=NULL;
  return 0;
}

 (引自鹏哥c语言) 

2.calloc函数:函数申明为void* calloc(size_t num,size_t size),也是向内存空间申请一个空间,但会初始化这个空间全部为0,函数参数与malloc有点不一样,如int* p=(int*)calloc(10,sizeof(int))。申请完后也需要释放空间。

#include
#include
#include
#include

int main()
{
  int* p=(int*)calloc(10,sizeof(int));
  if(p==NULL)
   {
     printf("%sn",strerror(errno));
   }
  else
   {
     int i=0;
     for(i=0;i<10;i++)
      {
        printf("%d ",*(p+i));
      }
   }
   free(p);
   p=NULL;
}

3.realloc函数:调整动态开辟空间的大小,函数申明:void*realloc(void* memblock,size_t size)。

#include
#include
#include
#include

int main()
{
  int* p=(int*)malloc(20);
  // 开辟不成功,打印不成功原因
  if(p==NULL)
   {
     printf("%sn",strerror(errno));
   }
  else
   {
     // 开辟成功,使用空间
     int i=0;
     for(i=0;i<10;i++)
      {
        *(p+i)=i;//依次为该空间赋值。
      }
  int* ptr=(int*)realloc(p,40);
  if(ptr!=NULL)
   {
     p=ptr;
     int j=0;
     for(j=0;j<10;j++)
      {
        *(p+j)=j;
        printf("%d ",*(p+j));
      }
   }
   free(p);
   p=NULL;
}
 





} 

4.动态内存分配常见错误:

    1).对空指针进行解引用操作,本质在于未对动态函数开辟的结果进行成功与否的判断,万一没有开辟成功,动态函数就返回空指针,对空指针解引用为非法。

    2).对动态开辟的内存的越界访问。

    3).对非动态开辟的空间使用free释放空间。

    4).使用free释放动态开辟的内存一部分。指向动态开辟的内存的指针变量在free空间之前,不能有任何改变值的操作,++pp++等,可以*(p+i)这种形式。

   5).对同一块动态开辟的空间进行多次释放。

   6).对动态开辟的空间忘记释放,导致内存泄漏。

5.几个经典的笔试题:

(一)

#include
#include
#include
 
void GetMemory(char* p)
{
  p=(char*)malloc(100);
}
void test(void)
{
  char* str=NULL;
  GetMemory(str);
  strcpy(str,"hello world");
  printf(str);
  return 0;
}
//test运行结果:程序崩溃。

问题分析:str里面是空指针,p里面倒是存放动态开辟空间的首地址,但是p出了GetMemory函数没有返回,所以被丢弃了,因此strcpy函数中str里面还是空指针,没有存放hello word的空间。程序在此就崩溃了。 另外会出现内存泄漏的问题,没有释放动态开辟的空间。

正确修改1(传值修改):

#include
#include
#include
 
char* GetMemory(char* p)
{
  p=(char*)malloc(100);
  return p;
}
void test(void)
{
  char* str=NULL;
  str=GetMemory(str);
  strcpy(str,"hello world");
  printf(str);
  free(str);
  str=NULL;
  return 0;
}

正确修改2.(传址修改:传址能够通过形参函数内部可以直接操作函数外部的变量。):

#include
#include
#include
 
void GetMemory(char** p)
{
  *p=(char*)malloc(100);
}
void test(void)
{
  char* str=NULL;
  GetMemory(&str);
  strcpy(str,"hello world");
  printf(str);
  free(str);
  str=NULL;
  return 0;
}

(二) 返回栈空间地址的问题

#include
#include

char *GetMemory(void)
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
//随机值,非法访问内存。

错误解释:返回栈空间地址,局部数组空间已还给操作空间了。即使返回了数组空间地址,里面的数据已变成随机值。

正确修改:用static修饰延长数组的生理周期。 

另外还需注意一个点,函数内部动态内存分配是在堆区开辟的,出了函数该空间不考虑丢失,但在栈区定义的变量空间会丢失。比如:

int* test()
{
  int* ptr=(int*)malloc(40);
  return ptr;
}
int main()
{
  int* p=test();
  return 0;
}

(三) 忘记释放空间,有内存泄漏之风险

#include
#include

void GetMemory(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
//test运行结果是,hello

虽然能打印,但没有释放空间,有内存泄露之风险。

 (四) 释放后的空间再次使用,非法访问

#include
#include

void Test(void)
{
char *str = (char *) malloc(100);
strcpy(str, "hello");
free(str);
if(str != NULL)
{
strcpy(str, "world");
printf(str);
}
}
//test运行结果是 world

正确修改free(str)后面添加str=NULL。逻辑才对。

 

 (引自鹏哥C语言) 

内核空间是留给操作系统的。数据段又叫静态区。 

6.柔性数组:C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做『柔性数组』成员。其中结构体中柔性数组是不占大小的。柔性数组大小的创建是通过malloc函数创建,并可以通过realloc函数来改变其大小。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/738555.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号