C/C++内存管理

简介: 1. 静态内存   静态内存是指在程序开始运行时由编译器分配的内存,它的分配是在程序开始编译时完成的,不占用CPU资源。程序中的各种变量,在编译时系统已经为其分配了所需的内存空间,当该变量在作用域内使用完毕时,系统会自动释放所占用的内存空间。

 1. 静态内存

  静态内存是指在程序开始运行时由编译器分配的内存,它的分配是在程序开始编译时完成的,不占用CPU资源。程序中的各种变量,在编译时系统已经为其分配了所需的内存空间,当该变量在作用域内使用完毕时,系统会自动释放所占用的内存空间。变量的分配与释放,都无须程序员自行考虑。

  eg:基本类型,数组

2. 动态内存

  用户无法确定空间大小,或者空间太大,栈上无法分配时,会采用动态内存分配。用malloc或者new申请任意多少的内存,程序员自己负责在何时用free或者delete手动释放内存。只用malloc或new分配的内存在堆里。

3.静态内存和动态内存的区别

  (1) 静态内存分配在编译时完成,不占用CPU资源; 动态内存分配在运行时,分配与释放都占用CPU资源。

  (2) 静态内存在栈(stack)上分配; 动态内存在堆(heap)上分配。

  (3) 动态内存分配需要指针和引用类型支持,静态不需要。

  (4) 静态内存分配是按计划分配,由编译器负责; 动态内存分配是按需分配,由程序员负责。

4.内存分配方式

  虚拟内存结构:

   

:这里谈的分配,都是指在虚拟内存中的分配。实际的分配需要做的是将虚拟地址映射到物理地址(段页式存储管理)。

内存分配方式一共有三种:

  (1)从静态存储区域分配(全局变量,静态变量,在虚拟内存的数据段

  内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,例如,全局变量,静态变量

  (2)在上创建(局部变量,在虚拟内存的栈,属于静态内存

  在执行函数时,函数内局部变量的存储单元都可以在上创建,函数执行结束后这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限

  (3)在上分配,亦称动态内存分配(malloc或者new申请,在虚拟内存的堆里,即在“空洞”里,属于动态内存)

  程序在运行的时候用malloc或者new申请任意多少的内存,程序员自己负责在何时用free或者delete手动释放内存。动态内存的生存期由程序员决定,使用非常灵活,但是问题也多。

5.内存释放问题

  (1)静态存储区域以及创建的栈,在函数执行完以后,出栈销毁,这个过程会自动释放静态分配的内存,不需要程序员手动操作;

  (2)而动态分配的内存,实际是在堆上,系统没法自动释放堆上的内存,需要程序员手动写free或者delete函数来告诉系统需要释放堆上哪个位置的内存;

6.常见的内存错误及对策

  (1)内存尚未分配成功,却使用了它;

  解决办法:在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口使用assert(p != NULL) 进行检查,如果是用malloc或者new来申请的,应该用if (p == NULL)或者 if (p != NULL) 来进行防错处理。

  (2)内存分配虽然成功,但是尚未初始化就引用它;

  错误原因:一是没有初始化的观念,二是误以为内存的缺省初值全为零,导致引用初值错误(如数组)。

  解决办法:内存的缺省初值是什么并没有统一的标准,尽管有些时候为零值,但是宁可信其有,不可信其无,无论以何种方式创建数组,都要赋初值。

int *p1,*p2;
int a=100,b=60;
p1=&a;
p2=&b;
//或者*p1=a;*p2=b;
printf("%d,%d\n",*p1,*p2);//100,60

  (3)内存分配成功并初始化,但是超过了内存的边界;

  这种问题常出现在数组越界,写程序是要仔细。

  (4)忘记释放内存,造成内存泄露

  含有这种错误的函数每次被调用都会丢失一块内存,开始时内存充足,看不到错误,但终有一次程序死掉,报告内存耗尽。

7.内存管理需要遵循的规则

  (1)用malloc 或者 new 申请内存之后,应该立即检查指针值是否为 NULL ,防止使用指针值为NULL的内存;

  (2)不要忘记数组和动态内存赋初值,防止未被初始化的内存作为右值使用;

  (3)避免数组或者指针下标越界,特别要当心“多1”或者“少1”的操作;

  (4)动态内存的申请与释放必须配对,防止内存泄露;

  (5)用free或者delete释放了内存之后立即将指针设置为NULL,防止产生“野指针”。

8.动态内存管理操作

  8.1动态内存分配

//函数说明
#include<stdio.h>
void *malloc(size_t size);
void *calloc(size_t nmemb,size_t size);

  (1)malloc的参数size表示分配的内存空间的大小,单位是字节Byte。

  (2)calloc的参数nmemb表示分配的内存空间占的数据项数目,参数size表示一个数据项的大小,单位是字节Byte。也就是说calloc分配的是nmemb X size大小的内存空间。

两者的区别是calloc将初始化所分配的内存空间,把所有位设置为0。

  (3)调用成功返回分配内存的地址,失败返回null。

  8.2动态内存释放

//函数说明
#include<stdio.h>
void free(void *ptr);

  动态内存示例:

#include<stdio.h>
#include<string.h>
char *upcase(char *inputstring);
int main(void)
{
  char *str1;
  str1=upcase("Hello");
  printf("str1 = %s \n",str1);
  free(str1);
  return 0;

} 
//子函数中动态分配的内存的指针返回到主函数中
char *upcase(char *inputstring)
{
  char *newstring;
  int counter;
  if(!(newstring=malloc(strlen(inputstring)+1))//为newstring分配动态内存,长度为strlen(inputstring)+1
  {
    printf("Error allocate memory!");
    exit(255);
  }
  
  strcpy(newstring,inputsreing);
  for(counter=0;counter<strlen(newstring);counter++)
  {
    if(newstring[counter]>=97 && newstring[counter]<=122)
    {
      newstring[counter]-=32;
    }
  }
  return newstring;
}
目录
相关文章
|
存储 程序员 编译器
玩转C++内存管理:从新手到高手的必备指南
C++中的内存管理是编写高效、可靠程序的关键所在。C++不仅继承了C语言的内存管理方式,还增加了面向对象的内存分配机制,使得内存管理既有灵活性,也更加复杂。学习内存管理不仅有助于提升程序效率,还有助于理解计算机的工作原理和资源分配策略。
|
10月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
340 26
|
11月前
|
C语言 C++
c与c++的内存管理
再比如还有这样的分组: 这种分组是最正确的给出内存四个分区名字:栈区、堆区、全局区(俗话也叫静态变量区)、代码区(也叫代码段)(代码段又分很多种,比如常量区)当然也会看到别的定义如:两者都正确,记那个都选,我选择的是第一个。再比如还有这样的分组: 这种分组是最正确的答案分别是 C C C A A A A A D A B。
194 1
|
存储 缓存 编译器
【硬核】C++11并发:内存模型和原子类型
本文从C++11并发编程中的关键概念——内存模型与原子类型入手,结合详尽的代码示例,抽丝剥茧地介绍了如何实现无锁化并发的性能优化。
724 68
|
存储 Linux C语言
C++/C的内存管理
本文主要讲解C++/C中的程序区域划分与内存管理方式。首先介绍程序区域,包括栈(存储局部变量等,向下增长)、堆(动态内存分配,向上分配)、数据段(存储静态和全局变量)及代码段(存放可执行代码)。接着探讨C++内存管理,new/delete操作符相比C语言的malloc/free更强大,支持对象构造与析构。还深入解析了new/delete的实现原理、定位new表达式以及二者与malloc/free的区别。最后附上一句鸡汤激励大家行动缓解焦虑。
|
安全 C语言 C++
彻底摘明白 C++ 的动态内存分配原理
大家好,我是V哥。C++的动态内存分配允许程序在运行时请求和释放内存,主要通过`new`/`delete`(用于对象)及`malloc`/`calloc`/`realloc`/`free`(继承自C语言)实现。`new`分配并初始化对象内存,`delete`释放并调用析构函数;而`malloc`等函数仅处理裸内存,不涉及构造与析构。掌握这些可有效管理内存,避免泄漏和悬空指针问题。智能指针如`std::unique_ptr`和`std::shared_ptr`能自动管理内存,确保异常安全。关注威哥爱编程,了解更多全栈开发技巧。 先赞再看后评论,腰缠万贯财进门。
614 0
|
存储 缓存 C语言
【c++】动态内存管理
本文介绍了C++中动态内存管理的新方式——`new`和`delete`操作符,详细探讨了它们的使用方法及与C语言中`malloc`/`free`的区别。文章首先回顾了C语言中的动态内存管理,接着通过代码实例展示了`new`和`delete`的基本用法,包括对内置类型和自定义类型的动态内存分配与释放。此外,文章还深入解析了`operator new`和`operator delete`的底层实现,以及定位new表达式的应用,最后总结了`malloc`/`free`与`new`/`delete`的主要差异。
331 3
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
796 4
|
存储 程序员 编译器
什么是内存泄漏?C++中如何检测和解决?
大家好,我是V哥。内存泄露是编程中的常见问题,可能导致程序崩溃。特别是在金三银四跳槽季,面试官常问此问题。本文将探讨内存泄露的定义、危害、检测方法及解决策略,帮助你掌握这一关键知识点。通过学习如何正确管理内存、使用智能指针和RAII原则,避免内存泄露,提升代码健壮性。同时,了解常见的内存泄露场景,如忘记释放内存、异常处理不当等,确保在面试中不被秒杀。最后,预祝大家新的一年工作顺利,涨薪多多!关注威哥爱编程,一起成为更好的程序员。
715 0
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。