首页
关于
Search
1
Lua使用调试库hook函数调用
705 阅读
2
傻瓜式快速搭建l2tp
634 阅读
3
游戏邮件系统数据设计因素
625 阅读
4
傻瓜式安装chatgpt-web工具
579 阅读
5
Linux内核数据结构kfifo小结(TODO)
574 阅读
项目技术
项目思考
开发环境
数据库
编程语言
生活与阅读
哲学
登录
Search
标签搜索
nodejs
npm
资深IT牛马
累计撰写
57
篇文章
累计收到
0
条评论
首页
栏目
项目技术
项目思考
开发环境
数据库
编程语言
生活与阅读
哲学
页面
关于
搜索到
57
篇与
的结果
游戏邮件系统数据设计因素
邮件系统基本是各个游戏必备基础功能,可以制作为跨项目通用功能。每个角色或者玩家可以通过“邮箱地址”来找到自己的邮件。
2021年06月27日
625 阅读
0 评论
0 点赞
盛最多水的容器
最简单的做法是平方时间复杂。实现O(n)主要思想是双端开始遍历。每次移动时,需要考虑选择左还是右指针向中间移动,目的是减少暴力平方遍历次数。当宽度递减1时,能够增加面积的情况只能有一种,那就是更高的短板。如果在前进过程中,短板更矮,则不需要算面积了,肯定变小
2021年06月26日
59 阅读
0 评论
0 点赞
罗马数字转整数问题
非常简单的道题目,当作重温算法的第一碟小记录下。过程中其实也重新回忆下CPP语法
2021年06月26日
17 阅读
0 评论
0 点赞
剑指 Offer 09. 用两个栈实现队列
栈是FILO结构,而队列是FIFO的结构。使用两个栈,一个用于正常的操作,一个用于遍历访问。通过再次逆向访问得到正向的访问结果。难度比较简单。
2021年06月26日
14 阅读
0 评论
0 点赞
2021-06-26
C程序内存空间
内存空间布局原理主要解决了我的这些疑问:内存空间中分哪些大类堆内存和栈内存地址谁大多个有前后关系栈变量或者堆内存地址大小关系malloc是如何分配内存的内存池的来由内存越界写为什么往往难以定位,如何防范。内存空间的组成部分正文段(Text Segment)。 CPU执行的指令数据段(DATA Segment)。这是指的是初始化数据段。比如明确赋值的全局变量。比如int maxcount = 99非初始化数据段(BSS Segment)。也称为BSS(block started by symbol)段。在程序开始执行前,内核将此段中的数据初始化为0或空指针。比如long sum[100]栈区。自动变量和函数调用时所需保存的信息,比如函数返回地址以及调用者环境信息、临时变量。这也是递归实现业务时需要考虑的代价。递归函数每次调用自身时,都会产生一个新的栈帧。一些脚本语言实现尾调用来优化这个情况。堆区。动态分配的内存。典型x86处理器Linux内存布局(存储器安排)从上到下,分别是高地址到低地址。Kernel space. 内核使用空间,有命令行参数和环境变量等。他的地址最大,大于0xC0000000栈区。栈底则在0xC0000000开始。栈分配从高地址向低地址方向增长。注意这和一个栈区数组地址加法来实现向前并不矛盾。栈变量指向的地址其实是这次分配段的末尾地址,于是地址的加法是没有问题的。一般一个栈帧大小是2MB。内存映射区。主要动态库文件和其他文件或者匿名内存映射使用空间。堆区。malloc、free是C标准的内存申请释放接口。在Linux下还是通过sbrk/mmap系统调用来实现的。注意malloc返回的指针一定是适当对齐的,使其可以用于任何数据对象。#include <stdio.h> #include <stdlib.h>// malloc是返回void*的,包含此文件可以避免强制类型转换 int main(int argc, char **argv) { int a, b; int *c = malloc(sizeof(int)); int *d = malloc(sizeof(int)); printf("%p\n%p\n%p\n%p\n", &a, &b, c, d); free(c); free(d); return 0; }因为手头没有x86机器,即使是x64其地址布局也相似,以下是输出:[anker@ms ~]$ gcc -o test test.c [anker@ms ~]$ ./test 0x7ffd3f14b80c 0x7ffd3f14b808 0x1a172a0 0x1a172c0可以留意到栈地址是减少方向。这里又可以联系到C语言参数入栈是从右往左。即书写在前面的参数越接近栈顶,也就是书写在前面的参数内存地址越低。所以32位下C语言处理变参va_arg就是指针地址加4.堆地址是增大的方向。同时我们也留意到再次malloc返回的地址差异大于两个int长度,这是因为分配的空间比要求的稍大一些。进一步的原因是,每次申请需要额外的空间来记录管理信息(分配块的长度,指向下一个分配块的指针等等)。也正是这个块管理记录所以越界写或者重复free,除了会修改另外一个块的程序内容,还可能严重的修改了其他块的管理信息。这种错误不会很快的暴露出来,导致了内存越界难以定位。目前在VS的调试模式下是有自动检测的,但Linux环境通过设置环境变量,支持附加调试功能。同时栈地址比堆地址大。虽然sbrk可以扩充或缩小进程的堆空间,但是大多数malloc/free的实现都是不实时减小进程的存储空间,原因有:释放的空间可供以后再分配,通常他们保持在malloc池中而不返回给内核。如果频繁的申请和释放,每次都调用sbrk或者mmap都增加了系统调用次数,从而影响性能。sbrk在高地址释放但中间有较低地址没有free时也无法收缩,这也是内存碎片产生原因。因为glibc等的内部自己实现了池式结构,小于某个阈值(默认128KB)时使用brk/sbrk实现内存分配。大于这个阈值则使用mmap申请匿名空间。mmap方式可以整段释放不容易有内存碎片。另外malloc/free在多线程下,需要进行锁操作。于是有了更高效tcmalloc和jemalloc实现。 tcmalloc是分线程和进程级别缓存的。使用glibc内存池可能会存在内存回收不及时,碎片过多问题,表面看起来和内存泄漏一样只增不减。
2021年06月26日
45 阅读
0 评论
0 点赞
1
...
8
9
10
...
12