热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c++和Java数组内存空间申请

c中由于数组导致的内存溢出处理之前实现图论算法的时候碰到过超大的整型数组,用c去实现着实会碰到一些莫名其妙的内存溢出问题。例如:我们想定义一个200

c++中由于数组导致的内存溢出处理

之前实现图论算法的时候碰到过超大的整型数组,用c++去实现着实会碰到一些莫名其妙的内存溢出问题。

例如:我们想定义一个 2000*2000 的 2d 数组,甚至是这样大小的 2d 的 vector,如果是直接定义成局部变量,那么将会直接报内存溢出错(大家可以计算一下这样大小的数组会占据多少内存空间)。

那么为什么定义成局部变量会导致内存溢出呢?笔者认为是因为程序中函数的调用或者说是运行其实是在栈中执行的,而栈的空间是很有限的,所以说定义过大的局部变量必然导致栈溢出(Stack overflow)错误。

因此对于较大的局部变量我们需要将其定义为全局的,尤其在函数的递归调用中。亲测 2d vector 当大小超过100,就已经能够导致溢出错了(vector 中的自增长方法会开辟更大的空间)。

众所周知,数组是一种顺序存储的数据结构,在定义数组时,首先要确定数组的大小。前面提到的静态数组在编译时就需要确定数组的大小,所以,为了防止内存溢出,我们尽量将数组定义的大一些,但是这样太过浪费内存。甚至当超过一定大小之后,编译会报错,例如直接定义一个全局的:

int a[3000][3000];

这样程序可能连编译都无法通过。

这样大型的数组需要通过定义动态数组。动态数组不需要在编译时就确定大小,它的大小在程序运行过程中确定,所以可以根据程序需要而灵活的分配数组的大小,相比静态数组,它更“灵活”、“自由”。但是动态数组需要进行显式的内存释放。

int **Ctable; // 全局的二次指针
void DynamicCreate2Array()
{// 二维动态数组的空间开辟 3000*3000大小int m &#61; 3000, n &#61; 3000;int i;cout << "############## call the CTable create func #############" << endl;//动态开辟空间 Ctable &#61; new int*[m]; //开辟行 for (int i &#61; 0; i < m; i&#43;&#43;)Ctable[i] &#61; new int[n]; //开辟列 int val &#61; 0;for (i &#61; 0; i < m; i&#43;&#43;)for (int j &#61; 0; j < n; j&#43;&#43;){Ctable[i][j] &#61; 0;val &#43;&#43;; } cout << "items: " << val << endl;
}
int main(){DynamicCreate2Array(); // 为CTable动态开辟内存int count &#61; 3000;//初始化Ctable全为0for(int i &#61; 0; i < count; i&#43;&#43;)for(int j &#61; 0; j < count; j&#43;&#43;)Ctable[i][j] &#61; 0;// 输出Ctablefor(int i &#61; 0; i < count; i&#43;&#43;)for(int j &#61; 0; j < count; j&#43;&#43;)printf("%d\t", Ctable[i][j]);//释放Ctable开辟的资源 for (int i &#61; 0; i < 3000; i&#43;&#43;)delete[] Ctable[i];delete[] Ctable;}

Java 中对大数组的处理

Java 程序在运行时都要开辟空间&#xff0c;任何软件在运行时都要在内存中开辟空间&#xff0c;Java虚拟机运行时也是要开辟空间的。JVM运行时在内存中开辟一片内存区域&#xff0c;启动时在自己的内存区域中进行更细致的划分&#xff0c;因为虚拟机中每一片内存处理的方式都不同&#xff0c;所以要单独进行管理。

JVM内存的划分有五片&#xff1a;


  1. 寄存器

  2. 本地方法区

  3. 方法区

  4. 栈内存

  5. 堆内存

我们重点来说一下堆和栈&#xff1a;


栈内存

栈内存首先是一片内存区域&#xff0c;存储的都是局部变量&#xff0c;凡是定义在方法中的都是局部变量&#xff08;方法外的是全局变量&#xff09;&#xff0c;for循环内部定义的也是局部变量&#xff0c;是先加载函数才能进行局部变量的定义&#xff0c;所以方法先进栈&#xff0c;然后再定义变量&#xff0c;变量有自己的作用域&#xff0c;一旦离开作用域&#xff0c;变量就会被释放。栈内存的更新速度很快&#xff0c;因为局部变量的生命周期都很短。


堆内存

存储的是数组和对象&#xff08;其实数组就是对象&#xff09;&#xff0c;凡是new建立的都是在堆中&#xff0c;堆中存放的都是实体&#xff08;对象&#xff09;&#xff0c;实体用于封装数据&#xff0c;而且是封装多个&#xff08;实体的多个属性&#xff09;&#xff0c;如果一个数据消失&#xff0c;这个实体也没有消失&#xff0c;还可以用&#xff0c;所以堆是不会随时释放的&#xff0c;但是栈不一样&#xff0c;栈里存放的都是单个变量&#xff0c;变量被释放了&#xff0c;那就没有了。堆里的实体虽然不会被释放&#xff0c;但是会被当成垃圾&#xff0c;Java有垃圾回收机制不定时的收取。

下面我们通过一个图例详细讲一下堆和栈&#xff1a;

比如主函数里的语句

int [] arr &#61; new int [3];

在内存中是怎么被定义的&#xff1a;

主函数先进栈&#xff0c;在栈中定义一个变量arr,接下来为arr赋值&#xff0c;但是右边不是一个具体值&#xff0c;是一个实体。实体创建在堆里&#xff0c;在堆里首先通过new关键字开辟一个空间&#xff0c;内存在存储数据的时候都是通过地址来体现的&#xff0c;地址是一块连续的二进制&#xff0c;然后给这个实体分配一个内存地址。数组都是有一个索引&#xff0c;数组这个实体在堆内存中产生之后每一个空间都会进行默认的初始化&#xff08;这是堆内存的特点&#xff0c;未初始化的数据是不能用的&#xff0c;但在堆里是可以用的&#xff0c;因为初始化过了&#xff0c;但是在栈里没有&#xff09;&#xff0c;不同的类型初始化的值不一样。所以堆和栈里就创建了变量和实体&#xff1a;
在这里插入图片描述
那么堆和栈是怎么联系起来的呢?

我们刚刚说过给堆分配了一个地址&#xff0c;把堆的地址赋给arr&#xff0c;arr就通过地址指向了数组。所以arr想操纵数组时&#xff0c;就通过地址&#xff0c;而不是直接把实体都赋给它。这种我们不再叫他基本数据类型&#xff0c;而叫引用数据类型。称为arr引用了堆内存当中的实体。&#xff08;可以理解为c或c&#43;&#43;的指针&#xff0c;Java成长自c&#43;&#43;和c&#43;&#43;很像&#xff0c;优化了c&#43;&#43;&#xff09;

如果当int [] arr&#61;null;

arr不做任何指向&#xff0c;null的作用就是取消引用数据类型的指向。

当一个实体&#xff0c;没有引用数据类型指向的时候&#xff0c;它在堆内存中不会被释放&#xff0c;而被当做一个垃圾&#xff0c;在不定时的时间内自动回收&#xff0c;因为Java有一个自动回收机制&#xff0c;&#xff08;而c&#43;&#43;没有&#xff0c;需要程序员手动回收&#xff0c;如果不回收就越堆越多&#xff0c;直到撑满内存溢出&#xff0c;所以Java在内存管理上优于c&#43;&#43;&#xff09;。自动回收机制&#xff08;程序&#xff09;自动监测堆里是否有垃圾&#xff0c;如果有&#xff0c;就会自动的做垃圾回收的动作&#xff0c;但是什么时候收不一定。

所以堆与栈的区别很明显&#xff1a;

1.栈内存存储的是局部变量而堆内存存储的是实体&#xff1b;

2.栈内存的更新速度要快于堆内存&#xff0c;因为局部变量的生命周期很短&#xff1b;

3.栈内存存放的变量生命周期一旦结束就会被释放&#xff0c;而堆内存存放的实体会被垃圾回收机制不定时的回收。

import java.util.Scanner;public class MyArray {public static void main(String[] args) {// 动态数组int col, row;Scanner sc &#61; new Scanner(System.in);String line &#61; sc.nextLine();String [] nums &#61; line.split(" ");col &#61; Integer.parseInt(nums[0]);row &#61; Integer.parseInt(nums[1]);System.out.println(col &#43; row);int [][] bigArray &#61; new int[col][row];for (int i &#61; 0; i < col; i&#43;&#43;) {for (int j &#61; 0; j < row; j&#43;&#43;) {bigArray[i][j] &#61; i &#43; j;}}System.out.println(bigArray[col-1][row-1]);}
}
/* 输入与输出
3000 3000
6000
5998
*/


推荐阅读
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 深入理解Java多线程并发处理:基础与实践
    本文探讨了Java中的多线程并发处理机制,从基本概念到实际应用,帮助读者全面理解并掌握多线程编程技巧。通过实例解析和理论阐述,确保初学者也能轻松入门。 ... [详细]
  • 2017-2018年度《网络编程与安全》第五次实验报告
    本报告详细记录了2017-2018学年《网络编程与安全》课程第五次实验的具体内容、实验过程、遇到的问题及解决方案。 ... [详细]
  • Java 类成员初始化顺序与数组创建
    本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ... [详细]
  • 深入理解Java泛型:JDK 5的新特性
    本文详细介绍了Java泛型的概念及其在JDK 5中的应用,通过具体代码示例解释了泛型的引入、作用和优势。同时,探讨了泛型类、泛型方法和泛型接口的实现,并深入讲解了通配符的使用。 ... [详细]
  • 本文提供了使用Java实现Bellman-Ford算法解决POJ 3259问题的代码示例,详细解释了如何通过该算法检测负权环来判断时间旅行的可能性。 ... [详细]
  • 本文详细介绍如何在VSCode中配置自定义代码片段,使其具备与IDEA相似的代码生成快捷键功能。通过具体的Java和HTML代码片段示例,展示配置步骤及效果。 ... [详细]
  • 本文详细探讨了Java中的ClassLoader类加载器的工作原理,包括其如何将class文件加载至JVM中,以及JVM启动时的动态加载策略。文章还介绍了JVM内置的三种类加载器及其工作方式,并解释了类加载器的继承关系和双亲委托机制。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • Java 中 Writer flush()方法,示例 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 数组元素逆序排列的实现
    本文介绍了一种简单有效的方法,用于将整数数组中的元素进行逆序排列。通过折半交换对应位置的元素,可以高效地完成这一任务。 ... [详细]
author-avatar
茶香未散尽_385_312
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有