人生如路,要有耐心。要想快乐地生活,就要学会一切随缘,不强求不可得,不执着已失去,淡定悠然,随遇而安。烦恼好比心中的黑暗,只有点亮随缘的心灯,才能驱散黑暗,照亮人生。
—-小新
一.内存分配方式
1.全局存储区域(静态存储区)
这种分配方式由编译器自动完成,在程序编译时就已经分配好内存。例如,全局变量和static变量就是在静态存储区域进行分配的。这种方式的优点是内存空间大小固定,且在整个程序运行期间都存在,直到程序运行结束时才被释放。
int global_var = 10; // 全局变量在编译时就已经分配好内存,整个程序运行期间都存在
2.在栈上分配
这种方式也由编译器自动完成。当函数被调用时,函数内部的局部变量都可以在栈上创建。当函数执行结束时,这些存储单元会被自动释放。这种方式的优点是分配和释放速度快,但是分配的内存容量有限。
void func() { // 函数执行时在栈上创建局部变量,执行结束时自动释放
int local_var = 20; // 局部变量在栈上分配内存
// 函数执行结束,局部变量自动释放
}
3.从堆上分配
这种方式也称为动态内存分配,它由程序员手动完成。程序员使用内存分配函数(如malloc或new)来申请任意大小的内存,使用完之后再由程序员自己负责使用内存释放函数(如free或delete)来释放内存。这种方式的优点是可以根据需要动态地申请和释放内存,但是需要程序员手动管理,容易造成内存泄漏。
int* ptr = NULL; // 指向动态内存的指针
ptr = (int*)malloc(sizeof(int)); // 在堆上分配内存,如果分配失败则返回NULL
if (ptr == NULL) {
printf("Memory allocation failed!n");
return -1; // 返回错误代码
}
*ptr = 30; // 写入动态内存的值
printf("The value of ptr is: %pn", ptr); // 输出动态内存的地址
printf("The value of *ptr is: %dn", *ptr); // 输出动态内存的值
free(ptr); // 释放动态内存,防止内存泄漏
二.堆和栈的区别
1.申请方式
堆:人为申请开辟。
2.空间大小
栈:获得的空间较小,一般为几MB;
堆:获得的空间较大。
3.申请效率
栈:由系统自动分配,速度较快;
堆:要依靠malloc等API申请,申请的过程比较复杂,速度比较慢。
4.存储内容
栈:在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的,静态变量存放在数据段;
堆:一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排。
5.底层
栈:连续的空间;
三.栈在c语言中的作用
1.保存局部变量和函数参数
在函数调用过程中,局部变量和函数参数会被存储在栈上。当函数执行结束后,这些变量和参数会被自动释放,从而为后续的函数调用腾出空间。
2.实现函数调用和返回
在C语言中,函数调用时会在栈上为其分配一个新的栈帧,包含函数的局部变量、参数和返回地址。当函数执行结束时,会从栈上弹出该栈帧,回到函数调用前的状态。
3.实现递归
递归函数会在每次递归调用时在栈上分配一个新的栈帧,从而实现了函数的嵌套调用。当递归结束时,会逐层返回,逐个释放栈帧。
4.实现动态内存分配
C语言中的动态内存分配通常使用堆来实现,但栈上也存在一种特殊的动态内存分配方式,即使用alloca函数在栈上分配内存。这种方式比堆分配要快,但可能会导致栈溢出或内存碎片问题。
四.内存泄漏
简单来说就是申请了内存,不使用之后并没有释放内存,或者说,指向申请的内存的指针突然又去指向别的地方,导致找不到申请的内存,
(1)影响
随着程序运行时间越长,占用内存越多,最终用完内存,导致系统崩溃。
(2)减少内存泄漏
1.良好的编码习惯,使用内存分配的函数,一但使用完毕之后就要记得使用对应的函数是否掉;
2.将分配的内存的指针以链表的形式自行管理,使用之后从链表中删除,程序结束时可以检查改链表;
五.字节对齐问题
数据在内存中的存储位置(即地址)是按照某个特定的规则进行对齐的。这个规则通常由计算机硬件和操作系统定义。对齐的目的是为了提高内存的访问效率,因为CPU通常一次只能读取固定大小的内存,如果数据没有对齐,就需要多次读取才能获取完整的数据。
字节对齐问题通常出现在低级编程语言如C/C++中,因为这些语言直接操作内存,需要程序员自己管理数据的存储。而在高级语言中,编译器通常会自动处理字节对齐的问题。
1.数据类型对齐
在定义数据结构或变量时,可以使用特定的数据类型来保证字节对齐。例如,在C++中,可以使用alignas关键字来指定数据的对齐方式。
2.填充
在某些情况下,可以在数据之间插入填充字节,以保证数据的对齐。这种方法通常用于处理跨多个内存地址的数据结构。
3.使用特定的编译器指令或属性
某些编译器提供了特定的指令或属性来控制字节对齐的方式。例如,在C++中,可以使用#pragma pack指令来控制数据结构的对齐方式。
总之,字节对齐问题是一个与内存管理和数据访问效率密切相关的问题。在编写低级语言或处理性能敏感的代码时,需要特别关注字节对齐问题。
原文地址:https://blog.csdn.net/weixin_66634995/article/details/134720952
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_41196.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!