项目场景:
项目场景:互助群同学在刷题的过程中,遇到的一个题目,需要申请一个很大数组,于是这个同学就写了
int[1000000]
,其实这样写也没有错,可是运行后却显示栈错误。于是就找到我来请教,我想就这个问题延申一下,在谈谈栈空间,堆空间等。
问题描述
#include<stdio.h>intmain(){int n,s[1000000],max,min,i,j;longlongint sum;double g;scanf("%d",&n);for(i=0;i<n;i++){scanf("%d",&s[i]);}
max=s[1];min=s[0];
sum=s[0]+s[1];if(s[0]>s[1]){
max=s[0];
min=s[1];}for(j=2;j<n;j++){if(s[j]>max)
max=s[j];if(s[j]<min)
min=s[j];
sum=sum+s[j];
g=1.0*(sum-max-min)/(j-1);printf("%.2lf",g);}return0;}
这里抛开逻辑不谈,在申请int s[1000000]时,就可能导致越栈空间的问题。许多初学者可能分不太清临时数组和动态数组的区别,所以会一直以来使用int s[1024]这种申请数组的形式,但是一旦申请的内存大就会出问题,这里题目要求10的6次方,就是考察你是否会使用动态申请内存。
解决方案:
我直接给出动态申请内存的代码,这不是我想讲的重点。重点放在原因分析
#include<stdio.h>#include<stdlib.h>intmain(){int* arr =(int*)malloc(1000000*sizeof(int));if(arr ==NULL){printf("内存分配失败\n");return1;}// 现在你可以使用 arr 指针来操作这个动态分配的数组// 例如,给数组赋值for(int i =0; i <1000000; i++){
arr[i]= i;}// 打印数组中的值for(int i =0; i <1000000; i +=100000){printf("%d ", arr[i]);}printf("\n");// 释放动态分配的内存free(arr);return0;}
原因分析:
计算机的栈空间和堆空间是两种不同的内存分配区域,它们在内存管理和使用方式上有一些重要的区别。
找到一张博主的图很不错转载:http://t.csdnimg.cn/jvgKJ这个博文讲的会很详细,我就不讲那么细了
先看一下两个地址的区别
栈空间(Stack):
栈空间是一种静态内存分配,由编译器自动分配和释放。
栈空间主要用于存储函数的局部变量、函数参数、函数调用的返回地址等。
栈空间的大小是固定的,通常比堆空间小,而且通常不需要手动管理。
栈空间的分配和释放是自动的,遵循“先进后出”的原则,即最后进入的数据最先出来。
堆空间(Heap):
堆空间是一种动态内存分配,需要手动分配和释放。
堆空间主要用于存储动态分配的内存,例如使用 malloc、new 等函数分配的内存。
堆空间的大小不固定,通常比栈空间大,需要手动管理分配和释放。
堆空间的分配和释放需要程序员手动控制,如果没有正确释放分配的内存,可能会导致内存泄漏等问题。
读完之后,你要知道int s[100000]就是在栈空间上找个这么多个连续的int内存准备好给你用,看图上Stack有个小箭头,代表内存向下生长,也就是说你一直无止尽的申请内存,就会往下跑,一旦跑到Memory区域,就会报错,告诉你,我没有内存可以申请使用了(Stack区域是比较小的,比heap小很多)。
讲个题外话,很早以前Stack是向上生长的,一旦到达kernel区域,就是计算机的底层核心代码区域,就可以对地址进行操作,达到控制计算机的目的,黑客也就是这么做的。
所以这个题目需要申请10的6次方,我们需要申请动态内存,而且这一块内存可以反复利用,一旦之前申请的内存free了,再次申请时,这一块内存就可以再度利用了。
版权归原作者 时义龙 所有, 如有侵权,请联系我们删除。