当前位置:首页 » 编程语言 » c语言内存问题
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

c语言内存问题

发布时间: 2022-01-13 06:56:17

‘壹’ c语言内存空间的问题

字符串占用字节为:有效长度+1个字节。
因为字符串尾部有一个\0

‘贰’ c语言关于内存释放问题

是InitStack(s)吧?程序里就没有InitSqlist()。
因为栈内容没有初始化,所以访问那个s->top时就出错了,并不是分配内存的malloc的问题。
把主函数里这两行改一下:
Stack *s; /* 这里没有给s分配内存,这只是一个Stack的指针*/
InitStack(s);
改为:
Stack s; /* 这样就给s分配空间了, s.top现在就可以用了*/
InitStack(&s);
这个问题就好了。

相应地,以后使用栈时注意使用指针就好:
ShowStack(s);
改为
ShowStack(&s);

还有一种做法,就是在:
Stack *s;
InitStack(s);
中间给指针s分配内存,让指针s指向正确的结构:
Stack *s;
s = (Stack*)malloc(sizeof(Stack));
InitStack(s);

‘叁’ c语言内存使用问题

补充一下:楼主说的“泄露”是错别字,本为“泄漏”,这下你再看应该好理解了吧。

================================================

1: 因为使用 static 声明的变量在全局中只有一个实例,也就是说如果你这样用的话:
char * a = itoa(10);
char * b = itoa(9);
之后,实际上 a 和 b 指向的是同一个 static 数组,它们当前值都是 "9"。

2: 内存泄漏说白了就是你使用了 new 在堆中创建了内容,而使用之后没有使用 delete 将之前申请的内存释放,这样申请的内存就算没有指向它的指针(也就是再也没有调用的时候),内存也依然被占用,这就是内存泄漏
他的方法就是叫你每次调用这个 itoa 的时候 new char[20] 这个样子。这样的话你不知道什么时候应该把内存释放掉,很容易造成内存泄漏。

举个例子:
char *itoa (int n)
{
char* retbuf = new char[20];
sprintf(retbuf, "%d", n);
return retbuf;
}

然后你调用
char * a = itoa(10);
如果要使这段内存脱钩之前不先释放:
delete [] a;
然后使他脱钩
a = itoa(9);
那么第一次调用的时候 new 出来的内存就泄漏掉了。。

‘肆’ c语言中内存问题

0xae34bcdf 是个16进制常数

%x %lx 都是表示操作数据按16进制进行处理
所以,输出就是这样子,不知道你所说的情况是这个吗?

‘伍’ 用C语言分配开辟内存问题

你的代码不是C的,其实现在语言比较强大,也许在内存回收上做了完善,我不会C++,我知道JAVA语言,他本身在内存回收上面做了优化,就是在堆中申请的内存,操作系统没回收,但JAVA语言最终编译成可运行码的时候,回收了这块内存(JAVA的垃圾回收机制,蛮强的,不过我不太喜欢)。你可以试试用C写,用malloc 来申请,这个应该不会被回收的,你可以试试,当然可能和其它原因有关。

最后如果你想学习内存管理的话,方向是:操作系统理论中的页式内存管理,地址的印射这2部分是理论(比较简单,实际情况比这复杂一点,先看理论比较好)
等真的明白了(应该不难懂),下面就有难度了,选一个比较流行的CPU的地址映射(各种不同的CPU地址映射是不一样的),我看的是intel 80386后出现的保护模式(其实是286后出现的,不过286没什么名气),以及linux中内存管理的源代码(记得结合书看,直接看代码很难懂)。
==========================================

你的问题算是有点难度和深度的。

关于内存开辟问题,在linux中有个很特殊的内存段,它的大小是8K,我们叫他系统堆栈空间,任何一段程序代码在运行时候它都是一个进程,它都会有这么一个8K的系统堆栈空间。局部变量都是放在这样一个8K空间中,包括int a,int a[100], int *a.他们都放在这里。

那么第一个问题就回答了,int a就是放在系统堆栈空间中。当这个进程死亡的时候,会有其它的进程来回收这个空间(它自己会指定的,一般是其父进程),所以你不需要自己手动去释放局部变量占地内存。

至于int * a;然后你new一个空间这个就有点不同了,首先 * a还是个局部变量,他是存在于系统堆栈中。不过它存的比较特殊是一个逻辑地址,不是一个值(其实逻辑地址也就是一个无符号的16位整数而已)。当你new 的时候,会在堆空间中开一个空间,并把这个空间的地址放到刚那个 a中去。很明显新申请的空间不是在系统堆栈空间中,父进程(一般是)是不会回收这个内存的,这就是为什么你要自己 free(a) 这样来释放空间。

我们常说局部变量不要过大,比如int a[10000]这是不允许的,可以看出来只有8K的大小的内存,而且他还不全部都是给局部变量使用,他有相当一部分内存是给进程控制块和中断返回现场用的(读过linux源代码你就清楚了),另外C语言不检查数组边界,如果你int a[4]数组,而不顾一切的向这个数组上放东西,你就有可能很运气的把中断的返回地址给冲掉,聪明的人会放一个新的返回地址进去,而这个地址返回一个恶意的进程。知道会发生什么了,这就是缓冲区溢出攻击。

windows虽然不太一样,但原理差不多。

‘陆’ C语言 内存的问题

一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值
等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能
由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初
始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态
变量在相邻的另一块区域。 - 程序结束后有系统释放
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。

所以你说的1不正确
2 文字常量区和代码区是独立,代码区存放编译后的代码 文字常量区 存放 字符串常量
比如char *p="123455"; 那这个“12345”就放在文字常量区 这个区域不能修改 p指向的内容不能修改

3malloc申请和new申请的在同一个位置 叫堆区 也叫自由存储区
4 malloc等

5解释是const申明的变量 如果不需要地址 编译器会给它优化 把它作为一个常量替换掉出现该变量的地方 比如const a=3;
后面 b=a+b; 编译器直接处理成
b=3+b;

‘柒’ c语言内存问题

如果是用malloc等函数获取的内存空间,需要自己调用相关函数释放;其他对象的生命期由编译器管理,生命期结束后自动释放……

‘捌’ c语言,大概是内存问题

函数局部变量不会自动初始化,需要软件初始化,如果不初始化,它的值是个随机数,是个不确定的数据,因为局部变量所在的内存空间是由系统来随机分配的,而这段内存有可能被其他程序使用过,所以里面的值是不确定的。
%s 只是个格式说明符,跟string.h 没有关系吧。

‘玖’ C语言中变量内存问题

(1)在函数中申明的变量,是局部量。
(2)函数没有被调用时,不给局部量分配空间。此时不占用内存空间。
(3)函数 局部量的生命周期是从调用开始到调用结束。
只有在调用函数时,才临时分配空间,函数调用并执行完毕时,空间就会被释放。
函数调用和执行中,无论是否使用此变量,它都要占用内存空间,有地址。
(4)更精确地说,同变量所在的域(就是一对花括号之间的区域)有关,生命周期从进域开始到出域结束。

‘拾’ c语言程序运行时 内存问题

以程序的具体执行过程为例来给你讲解,但愿你能理解:
1.程序被打开时,即程序开始运行时,会首先向操作系统请求独占内存空间(一段在程序整个执行过程中都不释放的空间),操作系统会应答请求并分配一段逻辑上连续(其实是将零散的内存空间映射为一段连续的空间)的内存空间给该程序,此时程序得到该段空间的逻辑地址信息,根据地址将程序代码段和数据段装入内存,此时程序载入完成。
2.程序运行中,当某一过程任务需要更大内存空间时,会再次向操作系统发出请求,操作系统会根据请求再次分配内存空间给该程序,当这一过程任务执行完毕后,该内存空间被释放。同时由于操作系统的存储保护,程序在运行过程中只能访问自己所申请的内存空间,不能访问其他程序的内存空间。
3.当程序执行完毕或关闭程序后,该程序所占的所有内存空间都被释放。
当你再次打开程序后,重复上面的过程。
下面对你的问题进行针对性回答:
1.当程序运行时,会调入内存,不同时间运行,程序放在内存的位置也可能不同:每运行一次程序,程序都会重新向操作系统申请内存空间,这时操作系统会分配一段全新的内存空间给程序,故不同时间运行程序,程序在内存中的位置是不同的。
2.使用内存中数据的位置也可能不同:当程序申请内存空间后,操作系统会将所申请的内存空间的地址传给程序,尽管数据的位置不同,但程序知道数据的地址,故程序依然可以根据地址来找到所需要的数据。