Skip to content

Commit f6b3f94

Browse files
committed
feat: Update stack20251124
1 parent 75b5d0b commit f6b3f94

File tree

3 files changed

+338
-2
lines changed

3 files changed

+338
-2
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
- 最近更新:2025.11.19
66

77
## netcom
8-
- [HAM等相关学习笔记](netcom/index.md)
9-
- 最近更新:2025.11.23
8+
- [通讯技术相关的学习笔记](netcom/index.md)
9+
- 最近都是Mesh相关
10+
- 最近更新:2025.11.24

netcom/content/stack20251124.md

Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
## 堆(heap)和栈(stack)
2+
3+
```
4+
那个“栈”经常会在各种文章里看到。
5+
先不管专业定义,先看一下外行也能稍微理解一下的意思。
6+
```
7+
8+
### 英文原本的意思
9+
10+
- stack
11+
- a stack of books → 一摞书
12+
- a stack of plates → 一叠盘子
13+
- a stack of papers → 一叠文件
14+
- stacked chairs → 椅子叠在一起
15+
16+
- heap
17+
- a heap of clothes → 一堆衣服(乱丢在床上的那种)
18+
- a heap of trash → 一堆垃圾
19+
- a heap of sand → 一堆沙子(倒在那里)
20+
- in a heap → 成一堆地摊着
21+
22+
stack和heap都是放东西,stack可以看到一层一层的,heap就是一堆团在一起。
23+
24+
---
25+
26+
### 先用大厨做饭的例子理解一下
27+
28+
👩‍🍳[大厨](https://fivsevn.home.blog/foodie/)在家做饭,要用到【厨房台面】和【冰箱/储物柜】。
29+
30+
---
31+
32+
> stack(栈):大厨手边的料理台工作区
33+
34+
- 大厨要:
35+
- 一边切菜
36+
- 一边放盘子
37+
- 一边放调味料
38+
- 一边丢临时用的餐巾纸啊什么的
39+
- 做完一步马上清掉,下一步再放新东西
40+
41+
```
42+
特点!
43+
· 用完即走
44+
· 只放当前步骤要用的东西
45+
· 顺序明确,越新的东西越放在“最上层”
46+
· 空间有限,挤满了就不好用了
47+
· 任务结束,台面会自动恢复空白
48+
```
49+
50+
- 大厨做完饭,stack(栈)就没了
51+
52+
---
53+
54+
> heap(堆):大厨的冰箱、放干货的储物柜等等。
55+
56+
- 大厨要:
57+
- 从冰箱拿肉肉
58+
- 再放回去一部分
59+
- 把昨天剩菜存进去
60+
- 把买回来的蔬菜塞进储物柜
61+
- 某些调料放进去放一个月都不动
62+
63+
```
64+
特点!
65+
· 容量大、可以随便塞
66+
· 用不用无所谓,可以放很久
67+
· 不按顺序,随便放
68+
· 要靠大厨手动整理,否则会越来越乱
69+
· 不会自动清理,除非你开冰箱清空
70+
```
71+
72+
- heap(堆)是个长期、无序、大容量的区域。
73+
74+
---
75+
### 对照计算机术语
76+
77+
- `从冰箱取肉``从heap取数据`
78+
- `放到料理台``在stack上创建临时变量`
79+
- `切肉、炒肉``运行函数,使用stack`
80+
- `用完的剩下食材放回冰箱``把需要长期存活的对象保存在heap`
81+
- `做完饭把料理台清空``函数结束,stack自动清理`
82+
- `冰箱里还留着没用完的东西``heap的对象继续存在,等待 GC 或释放`
83+
84+
--
85+
### 让GPT给了几个具体的使用场景,随便熟悉一下
86+
87+
#### 一、Stack 在真实开发里的典型用法
88+
89+
例句 1:函数里放太多东西,stack 会爆
90+
91+
> “别在函数里定义 20MB 的数组,stack 会直接爆掉。”
92+
93+
场景:
94+
某人写了一个函数,里面搞了个巨大的临时数组,程序直接崩。
95+
96+
真实原因:stack 空间固定(比如只有 1MB),装不下。
97+
98+
99+
100+
例句 2:这个变量别放 stack 上,生命周期太短
101+
102+
> “你要返回这个对象,不能放 stack,它出了函数就没了。”
103+
104+
场景:
105+
新手把一个结构体声明在函数里,还 return 它的地址。
106+
运行结果:指针指向的内存瞬间消失。
107+
108+
stack 变量 = 函数结束即消失。
109+
110+
111+
112+
例句 3:递归太深了,Stack Overflow(栈溢出)
113+
114+
> “这递归 5000 层了,stack 顶不住。”
115+
116+
场景:
117+
深度递归每进入一层,就压一层 stack frame,最后爆掉。
118+
119+
你肯定听过 Stack Overflow(程序错误,不是那个网站),就是字面含义。
120+
121+
122+
123+
例句 4:这个函数调用链太长,stack 占用很大
124+
125+
> “这个算法层级太深,stack frame 撑满了,得改循环写法。”
126+
127+
场景:
128+
函数 A 调 B 调 C 调 D……
129+
每一层都在 stack 上放一帧。
130+
131+
132+
133+
#### 二、Heap 在真实开发里的典型用法
134+
135+
例句 1:别忘了 free,不然 heap 会泄漏(内存泄漏)
136+
137+
> “你 malloc 了不 free,这程序跑一小时 heap 都被你泄得差不多了。”
138+
139+
场景:
140+
常见 bug:申请 heap 空间但忘了释放。
141+
142+
heap 内存泄漏就像你冰箱里丢垃圾,不清会越来越多。
143+
144+
145+
146+
例句 2:这个对象很大,放 stack 不行,放 heap
147+
148+
> “这个 10MB 的结构必须 new 分配,stack 放不下。”
149+
150+
场景:
151+
大对象必须放 heap,stack 会爆。
152+
153+
154+
155+
例句 3:GC(垃圾回收)在清 heap
156+
157+
> “程序卡一下,是在做 heap 的垃圾回收。”
158+
159+
场景:
160+
Java / Go / Python 某次停顿:
161+
垃圾回收器正在整理 heap。
162+
163+
你能想象成:程序暂停一下清冰箱。
164+
165+
166+
167+
例句 4:Heap 碎片太严重了,得 compact 一下
168+
169+
> “堆碎片太多了,GC compact 一下才能挤出连续空间。”
170+
171+
场景:
172+
heap 会碎掉变成不连续的小块,导致申请大对象失败。
173+
174+
stack 永远不会碎片化,heap 会。
175+
176+
177+
178+
例句 5:这个对象生命周期不确定,用 heap 合适
179+
180+
> “这个状态要跨好几个函数,用 heap 存吧。”
181+
182+
场景:
183+
程序里长期存在的对象,比如用户会话、游戏角色。
184+
185+
186+
187+
#### 三、Stack 和 Heap 一起出现的真实语境
188+
189+
例句 1:stack 上放指针,heap 才放真实数据
190+
191+
> “别搞混了,你在 stack 上放的是指向 heap 的指针,不是对象本身。”
192+
193+
场景:
194+
常见误区:
195+
以为 new 出来的对象在 stack 上,实际上:
196+
• stack:存指针
197+
• heap:存对象
198+
199+
200+
201+
例句 2:stack frame 分配很快,heap 分配要走 allocator
202+
203+
> “这个函数很快,因为全是 stack 分配,没有 heap 分配。”
204+
205+
场景:
206+
性能优化时常说:stack 分配快如闪电,heap 慢得多。
207+
208+
209+
210+
例句 3:为了性能,减少 heap 分配,多用 stack
211+
212+
> “GC 太慢了,把短期对象都放到 stack 上更快。”
213+
214+
场景:
215+
高性能服务器里,程序员会尽量减少 heap 分配。
216+
217+
218+
219+
例句 4:不要从 stack 返回地址,不然指向无效内存
220+
221+
> “你返回了一个 stack 地址,出了函数这个东西已经没了。”
222+
223+
场景:
224+
C/C++ 新手经典错误。
225+
226+
227+
228+
例句 5:这个对象生命周期不匹配,应该从 stack 改到 heap
229+
230+
> “这个对象要跨函数用,别放 stack。”
231+
232+
场景:
233+
设计对象生命周期时的常见讨论。
234+
235+
236+
237+
#### 四、最典型的真实场景故事(完整体验 stack 和 heap)
238+
239+
场景:处理用户请求(一个 Web 服务器)
240+
241+
- 1)请求进来
242+
程序开一个线程 / 协程 → 新建 stack
243+
像料理台一样准备好临时空间
244+
245+
- 2)解析用户输入
246+
临时变量、局部字符串 → 放 stack
247+
248+
- 3)要查询数据库,结果要返回给前端
249+
数据结构 → 放 heap(因为需要长期存在一会儿)
250+
251+
- 4)stack 上创建指向 heap 数据的指针
252+
就像料理台放一张便签写“冰箱有鸡肉(heap 地址)”
253+
254+
- 5)请求结束
255+
stack 自动消失
256+
heap 中的对象如果不再需要 → GC 或 free
257+
258+
259+
260+
#### 五、拿【处理 Meshtastic / LoRa 节点上传的数据】举例
261+
262+
python
263+
264+
```python
265+
def handle_message(node_id, raw_payload):
266+
# ------------- STACK(函数临时工作区)-------------
267+
# 这些变量存在于函数调用期间,用完就被丢弃
268+
269+
parsed = raw_payload.decode(”utf-8“) # 临时解析结果 → stack
270+
print(f”收到节点 {node_id} 的消息:{parsed}“)
271+
272+
# 创建一个临时 dict(仍在 stack 上,短期变量)
273+
result = {
274+
”node“: node_id,
275+
”text“: parsed,
276+
}
277+
278+
# 调用另一个函数,把 result 传下去
279+
store_message(result) # result 会作为“值”传递,但引用活在 heap(见下)
280+
# ---------------------------------------------------
281+
282+
283+
def store_message(msg):
284+
# ------------- STACK(此函数自己的临时空间)-------------
285+
# msg 是一个引用变量,放在 stack
286+
# 但 msg 真实内容(dict)在 heap
287+
288+
print(”正在保存消息...“)
289+
290+
# 这个 append 会把 msg(字典对象)放入 heap 里的全局列表
291+
MESSAGE_DB.append(msg) # 这里的 MESSAGE_DB 和里面的对象在 heap
292+
# ---------------------------------------------------
293+
294+
295+
# ------------- HEAP(进程长期存放数据的区域)-------------
296+
# 程序运行期间一直存在,只要你不关程序,这里就不会消失
297+
298+
MESSAGE_DB = [] # 全局列表 → heap,存活时间 = 程序整个生命周期
299+
300+
# ----------------------------------------------------------
301+
302+
303+
# 模拟收到一条 LoRa / Meshtastic 数据
304+
handle_message(”node_01“, b”Hello Mesh“)
305+
handle_message(”node_02“, b”GPS: 31.2304,121.4737“)
306+
307+
print(”\n所有存档的消息:“)
308+
for m in MESSAGE_DB:
309+
print(m)
310+
```
311+
312+
运行结果:
313+
314+
- 两次 handle_message 的临时变量全部消失(stack 自动清空)
315+
-MESSAGE_DB 仍然保存消息在 heap(长期存活)
316+
317+
```text
318+
收到节点 node_01 的消息:Hello Mesh
319+
正在保存消息...
320+
收到节点 node_02 的消息:GPS: 31.2304,121.4737
321+
正在保存消息...
322+
323+
所有存档的消息:
324+
{’node‘: ’node_01‘, ’text‘: ’Hello Mesh‘}
325+
{’node‘: ’node_02‘, ’text‘: ’GPS: 31.2304,121.4737‘}
326+
```
327+
328+
---
329+
目前不一定要全部都看懂,但是可以理解一下意思。
330+
331+
332+
333+

netcom/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
(更新中...)
1010

11+
- 2025.11.24 [堆(heap)和栈(stack)](content/stack20251124.md)
12+
1113
- 2025.11.23 [LoRa开发板可以做些什么](content/lora20251123e.md)
1214

1315
- 2025.11.23 [从内容到电磁波,以及LoRa这种调制方式](content/lora20251123.md)

0 commit comments

Comments
 (0)