Golden Blonde 发表于 2022-5-12 00:17:31

【VB6】最简单的“栈”演示

栈是一个“先进后出”的数据结构,非常类似现实世界中的弹匣(第一发压入的子弹最后一发射出)。实际应用举例:做多标签浏览器时,每关闭一个TAB之前,就把TAB的URL记录一下;如果用户按下CTRL+SHIFT+T,就重新打开刚才被关闭的页面。利用VB自带的动态数组,可以用极少的代码实现栈结构。把下面的代码保存在FRM文件后,双击打开即可运行。DEMO里的PUSH按钮是压栈,每次给栈里压入一个数字;POP按钮是弹栈,一次性把栈里的内容全部弹出。
**** Hidden Message *****

0xAA55 发表于 2022-5-12 09:24:10

此处可以顺带讨论一下 Java 和 C# 的堆内存管理。虽然是堆,但是长得像栈一样,你 new 的时候,相当于从栈上 push;但是你不需要 delete,因此没有 pop。当空间满了的时候,GC 触发,暂停线程,然后从线程上下文寄存器、栈上的局部变量、堆上结构体和类里面的成员变量里进行扫描,找出所有的指针,其指向内容被标记为“正在被使用”,其余的就是要被回收的“垃圾”了,然后把所有正在被使用的数据 memcpy 到“起点”,并且重新计算所有的指针值,再赋值回去,然后再恢复所有被暂停的线程的运行。

xiawan 发表于 2022-5-13 15:34:34

如此好贴,必须支持~~~

usr 发表于 2022-5-13 21:20:28

0xAA55 发表于 2022-5-12 09:24
此处可以顺带讨论一下 Java 和 C# 的堆内存管理。虽然是堆,但是长得像栈一样,你 new 的时候,相当于从栈 ...

站长研究过伙伴系统没,伙伴系统是一种巧妙地内存管理系统,虽然不能完全消除内存你碎片,但能很大程度上减少内存碎片的产生。

0xAA55 发表于 2022-5-13 22:31:11

usr 发表于 2022-5-13 21:20
站长研究过伙伴系统没,伙伴系统是一种巧妙地内存管理系统,虽然不能完全消除内存你碎片,但能很大程度上 ...

没有。细说?

usr 发表于 2022-5-13 23:35:32

本帖最后由 usr 于 2022-5-13 23:46 编辑

0xAA55 发表于 2022-5-13 22:31
没有。细说?


请看这张图。

简而言之,伙伴系统就是把给定的内存一半一半劈开,将大小合适的一半分配出去。回收内存时将空闲的两半合并。

0xAA55 发表于 2022-5-14 22:18:37

usr 发表于 2022-5-13 23:35
请看这张图。

简而言之,伙伴系统就是把给定的内存一半一半劈开,将大小合适的一半分配出去。回收内存 ...

现有的 C 标准库的 malloc 在底层貌似已经是这样的实现了。

Golden Blonde 发表于 2022-5-15 08:58:10

0xAA55 发表于 2022-5-14 22:18
现有的 C 标准库的 malloc 在底层貌似已经是这样的实现了。

我似乎感觉,malloc和VirtualAlloc分配的不是同一种内存,这俩函数不能混用(不能“用malloc申请,用VirtualFree释放”)。

此外,一些远古时代的程序还用HeapAlloc/HeapFree,话说这玩意是啥?

tlwh163 发表于 2022-5-15 09:03:11

xuexixuexi

0xAA55 发表于 2022-5-15 13:42:46

美俪女神 发表于 2022-5-15 08:58
我似乎感觉,malloc和VirtualAlloc分配的不是同一种内存,这俩函数不能混用(不能“用malloc申请,用Virt ...

VirtualAlloc 分配下来的内存按页算,而 malloc 分配下来的内存按字节算。事实上,malloc 是从 VirtualAlloc 分配下来的内存里分配内存。

HeapAlloc 和 HeapFree 可以理解为一种私有内存池,它的分配释放可以在堆的内部管理,不用干涉整个进程内存空间。

唐凌 发表于 2022-5-15 23:19:51

美俪女神 发表于 2022-5-15 08:58
我似乎感觉,malloc和VirtualAlloc分配的不是同一种内存,这俩函数不能混用(不能“用malloc申请,用Virt ...

VirtualAlloc直接走内核,分配的粒度按页对齐,可以直接在进程的VAD树里找到。VAD树是AVL的二叉树,按地址排序,保障平衡,找起来很快。
malloc不会走到内核,除非堆内存不足。分配的对齐粒度看堆,比如Win32的8字节,Win64的16字节。
详情见Chapter 5 "Memory Management", Windows Internals (Part 1), 7th Edition.

冰岚时空 发表于 2022-5-18 02:22:38

刚开始学 不知道能不能看懂 看了再说:(

Golden Blonde 发表于 2022-5-18 17:59:37

0xAA55 发表于 2022-5-15 13:42
VirtualAlloc 分配下来的内存按页算,而 malloc 分配下来的内存按字节算。事实上,malloc 是从 VirtualAl ...

WINDOWS的“堆”实际上是啥呢?不可能是CPU的内部存储器(比如缓存)吧,我感觉其实还是内存啊。

Golden Blonde 发表于 2022-5-18 18:00:27

tangptr@126.com 发表于 2022-5-15 23:19
VirtualAlloc直接走内核,分配的粒度按页对齐,可以直接在进程的VAD树里找到。VAD树是AVL的二叉树,按地 ...

“堆内存”?换句话说,malloc和free实际上是HeapAlloc和HeapFree?

唐凌 发表于 2022-5-18 19:57:24

美俪女神 发表于 2022-5-18 18:00
“堆内存”?换句话说,malloc和free实际上是HeapAlloc和HeapFree?


堆就是Heap。通常来说,`malloc`的最终实现就是`HeapAlloc`。
一般说申请内存就分为从堆上分配(`malloc`)和从栈上分配(`alloca`或者局部变量)。
前者是运行时的,涉及多线程,分配要获取锁,速度比较慢。
后者是编译时的,无关多线程,只需要对esp/rsp作减法即可,速度很快。
通常来说,为了高性能地给多线程分配堆内存,设计者会提前创建多个堆,保证线程之间不会因为分配堆内存而造成等待。

Golden Blonde 发表于 2022-5-18 21:46:08

tangptr@126.com 发表于 2022-5-18 19:57

堆就是Heap。通常来说,`malloc`的最终实现就是`HeapAlloc`。
一般说申请内存就分为从堆上分配(`ma ...

我忽然明白为啥有些古老程序用HeapAlloc而不是VirtualAlloc了。

在上古时代内存也就16到64MB,VirtualAlloc一下,可用内存就少了4KB,多VirtualAlloc几下,内存就用完了。而大多数情况下,申请内存也就需要几十到几百字节而已(路径、结构体等),所以用HeapAlloc是最佳选择。

后来随着内存越来越大,现在的内存普遍是16到64GB,所以也就没人在乎HeapAlloc和VirtualAlloc的区别了。

watermelon 发表于 2022-5-19 09:29:00

牛逼,支持!

0xAA55 发表于 2022-5-19 12:35:30

美俪女神 发表于 2022-5-18 17:59
WINDOWS的“堆”实际上是啥呢?不可能是CPU的内部存储器(比如缓存)吧,我感觉其实还是内存啊。 ...

就是内存。

W741 发表于 2022-5-24 17:28:05

学习学习
页: [1]
查看完整版本: 【VB6】最简单的“栈”演示