主頁 > 軟體設計 > 圖解函式堆疊幀 - 函式的創建與銷毀

圖解函式堆疊幀 - 函式的創建與銷毀

2021-10-05 09:09:40 軟體設計

函式堆疊幀

  • 🎂前言
  • 🌹堆疊幀的概念
  • 💖準備作業
  • 😀main函式堆疊幀的創建及初始化
      • 😁main函式的被呼叫
      • 😂main函式堆疊幀的開辟
      • 🤣main函式堆疊幀的初始化
  • 👩臨時變數的創建,
  • 👨Add函式堆疊幀的創建
      • 🧑Add函式堆疊幀的創建
      • 👧Add函式堆疊幀的初始化
  • 🎈Add函式實作加法運算
  • 🧨Add函式回傳值實作
      • 🎆Add函式堆疊幀的銷毀
      • 🎇回傳到main函式指令
  • 🍕🍕總結

🛸🛸文章開始之前,我想對各位提幾個問題,看看你們能答出幾個,看完本文之后,你們又能回答出幾個?

  • 區域變數是怎么創建的?
  • 為什么區域變數的值是隨機值?
  • 函式是怎么傳參的?傳參的順序是怎樣的?
  • 形參和實參是什么關系?
  • 函式呼叫是怎么做的?
  • 函式呼叫結束后是怎么回傳的?

🎂前言

研究的函式: 一個加法函式,

原因:加法函式是比較簡單的函式,實作邏輯比較單一,可以更為清楚的觀察到函式堆疊幀的創建和銷毀,而不是花費更多精力去研究復雜的函式,

#include <stdio.h>

int Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}

int main()
{
	int a = 10;
	int b = 20;
	int c = 0;

	c = Add(a, b);
	printf("%d\n", c);

	return 0;
}

使用的編譯器: VS2013,

原因:版本過高過新的編譯器在對堆疊幀分配上進行的封裝處理較為完善,我們在學習時不易于看清楚里面的具體步驟,較低版本的編譯器在學習時較為友好,
VS2013

研究的方法: 圖解,

原因:本文將以畫圖、截圖配上文字解釋加以說明,可以更加直觀的理解函式堆疊幀的分配情況,
畫圖工具

🌹堆疊幀的概念

堆疊幀是指為一個函式呼叫單獨分配的那部分堆疊空間, 比如,當運行中的程式呼叫另一個函式時,就要進入一個新的堆疊幀,原來函式的堆疊幀稱為呼叫者的幀,新的堆疊幀稱為當前幀, 被呼叫的函式運行結束后當前幀全部收縮,回到呼叫者的幀,

💖準備作業

  1. 將代碼編輯在編譯器中,

代碼文本編輯

  1. 開始除錯并按下滑鼠右鍵,(按下F10)

點擊轉到反匯編

  1. 轉到反匯編,
    反匯編

😀main函式堆疊幀的創建及初始化

😁main函式的被呼叫

首先我們需要明確,main()函式也就是我們平時說的主函式,他其實也是需要被其他函式呼叫的,

  1. 我們先在除錯狀態下打開呼叫堆疊視窗,
    打開呼叫堆疊視窗

顯示如下:

呼叫堆疊視窗

  1. 接下來我們一直按F10進行除錯,直到主函式return 0被回傳,即可出現以下界面,

main函式被呼叫情況

往上翻即可找到呼叫main()函式的函式,

呼叫main函式的函式
也就是說main()函式其實是被一個叫__tmainCRTStartup的函式所呼叫的,


😂main函式堆疊幀的開辟

我們知道,函式和區域變數的開辟是在堆疊上完成的,并且堆疊的使用習慣是先使用高地址,后使用低地址,

假設堆疊空間如下:

堆疊空間

我們知道main函式也是被其他函式呼叫的,所以在堆疊上其實還有編譯器為__tmainCRTStartup函式開辟的空間,這一點心中要明確,

接下來我們看反匯編里的匯編指令:

匯編指令

這一部分匯編指令其實就是對main函式的堆疊幀進行開辟,

這里介紹一下大家對指令里陌生的東西:

暫存器:ebp,esp,ebx,esi,edi,ecx,eax等等,

其中我們需要著重記住幾個暫存器的功能,

維護函式堆疊幀的暫存器:

  1. esp - 存放指向堆疊頂的地址的暫存器,
  2. ebp - 存放指向堆疊底的地址的暫存器,

初始化函式值的暫存器:

  1. edi - 用于存放開始進行初始化的地址,
  2. ecx - 用于存放初始化元素的數量,
  3. eax - 用于存放將要初始化為什么東西的內容,

下面先給出在執行main函式之前堆疊的情況:

__tmainCRTStartup函式堆疊幀

這里是編譯器為__tmainCRTStartup函式開辟的函式堆疊幀,可以看見,ebp暫存器指向堆疊底,esp暫存器指向堆疊頂,以此來維護__tmainCRTStartup函式的函式堆疊幀,

下面我們一一分析main函式的匯編指令操作:
匯編指令

push        ebp

指將ebp暫存器中的值進行壓堆疊操作(push),

即在編譯器已為__tmainCRTStartup函式開辟的堆疊幀上面進行壓堆疊,

壓堆疊操作

因為esp是指向堆疊頂的暫存器,所以每次壓堆疊之后esp暫存器所指的位置會上升,反之如果執行pop彈出的操作,esp暫存器所指的位置則會下降,

esp位置上升

此時__tmainCRTStartup函式的函式堆疊幀也隨之增加,

堆疊幀增加

下一個操作,

匯編指令

mov            ebp,esp

這條操作的指令是將esp的值賦給ebp,

也就是說讓esp里存放所指向的地址賦給ebp,那么ebp所指向的位置將會發生更改,

ebp位置發生更改
此時ebp和esp指向了同一位置,

但是注意:

  1. 此時ebp和esp沒有在維護__tmainCRTStartup函式了,但不代表他的函式堆疊幀被銷毀了,因為堆疊空間的使用只能先銷毀低地址,再銷毀高地址,
  2. 將來main函式回傳之后,esp暫存器和ebp暫存器還是要回來維護__tmainCRTStartup函式的,這里第一條指令push的ebpc操作就是伏筆,在main函式回傳值后會執行pop這個ebp的操作,直接把ebp暫存器彈向之前存放的位置,也就是__tmainCRTStartup函式的堆疊底,

再下一個操作:

匯編指令

sub          esp,0E4h

這里解釋一下,sub就是減法操作,這里0E4h表示十六進制的數字,h為識別符號,所以0E4h其實就是十進制的228,

合起來就是將esp里存放的地址減去0E4h的大小,

因為上面是低地址下面是高地址,所以減去0E4h應該是向上走,

esp向上0E4h

現在ebp和esp所維護的這段空間就是為main函式開辟的函式堆疊幀,

main函式堆疊幀

至此,main函式的函式堆疊幀就開辟完成了,


🤣main函式堆疊幀的初始化

我們在寫代碼的時候一定出現過一個問題,就是使用未初始化的變數或內容進行列印,結果控制臺輸出的東西完全是我們意想不到的結果,例如:

隨機值
為什么這里會出現隨機值呢?

下面就可以給出答案,

匯編指令

下面三條指令全部是push,

push                    ebx
push                    esi
push                    edi

三次push操作

三次push壓堆疊之后,esp的位置自動發生變化,main函式的函式堆疊幀也隨即增大,

匯編指令

接下來:
lea: load effective address(加載有效地址)

lea                                 edi,[ebp - 0E4h]

前面介紹過幾個重要的暫存器:

介紹暫存器
所以這里的edi是用來存放開始進行初始化的地址的,也就是把【ebp - 0E4h】這個地址放進edi保存起來,

匯編指令

下面兩個操作都是針對初始化用的暫存器的:

mov                          ecx,39h
mov                          eax,0CCCCCCCCh

ecx是存放初始化內容的次數的,所以是把39h這個次數存放在暫存器ecx中,

而eax是存放要初始化為的內容的,所以將0CCCCCCCCh存放進eax暫存器中,

接下來的指令就是初始化的關鍵:

rep stos                dword  ptr es:[edi]

dword的意思是double word - 一個word是兩個位元組,所以一個dword是4個位元組,

整個指令的意思是從edi存放的位置開始往下每四個位元組算一次,重復ecx里存放的值這么多次,把這些內容全部改為eax里存放的值,

也就是從ebp - 0E4h位置開始往下39h個整型的位置全部初始化為0CCCCCCCCh

至此main函式堆疊幀里的內容已被全部初始化,

記憶體內容

此時堆疊里的情況:

堆疊里的情況

為了防止有的碼友不相信,這里我們計算一波,

十六進制39h轉換成十進制是57,

計算器
57次,一次4個位元組,也就是57乘以4等于228個位元組,

而十六進制0E4h轉化為十進制正號等于228,

計算器
所以至此,main函式堆疊幀里的所有內容全部被初始化為0CCCCCCCCh,


👩臨時變數的創建,

匯編指令

這里的指令看的不夠清晰,因為編譯器默認顯示了變數名,這不適合我們學習具體情況,所以我們應該把顯示變數名給勾選掉,

點擊
勾選掉

把勾選去掉即可,效果如下:

勾選掉后的效果

這里就可以把具體位置看的比較清晰,

move                         dword ptr [ebp-8],0Ah

十六進制的0Ah轉換成十進制也就是10,這條指令的意思就是將0Ah這個數放進[ebp-8]的位置,

也就是把ebp-8這個位置分配給變數a,將里面的值賦為10,

給a開辟空間并賦值

匯編指令

move                                  dword ptr [ebp-14h],14h

同上,這里的十六進制數字14h轉換為十進制是20,將20放進[ebp-14h]的位置,

給b開辟空間并賦值

匯編指令

move                         dword ptr [ebp-20],0

同上,將0賦給[ebp-20h]的位置,也就是為c變數開辟空間并賦值,

給變數c開辟空間并賦值

匯編指令
看起來似乎到了函式呼叫了,但其實不然,呼叫函式之前,先在主調函式內創建實參的臨時拷貝,再進行呼叫函式,接下來一一分析,

move               eax,dwor ptr [ebp-14h]

這句指令的意思是將[ebp-14h]位置存放的值賦給eax暫存器,

而我們可以看到:ebp - 14h的位置不就是我們剛剛創建的b變數嗎?

這個操作把實參b的值存放到了暫存器eax中,

下一指令:

push               eax

將eax壓堆疊,這里我們記住eax中存放的值就是實參b的值,

push
匯編指令

move            ecx,dword ptr [ebp-8]
push             ecx

同上,將[ebp-8]位置的值放在ecx里,之后將ecx壓堆疊,

而ebp-8位置放的就是a變數,

壓堆疊

執行到這里,其實就不難看出上面的操作其實是在給Add函式傳參,開辟兩個空間存放實參的臨時拷貝,

注意: 這里傳參的順序是先傳b后傳a,并且是在main函式的堆疊幀內部進行的,

👨Add函式堆疊幀的創建

在創建Add函式的函式堆疊幀之前,編譯器還做了一件事情:

匯編指令

call                             00B910E1

乍一看這個指令非常奇怪,但我們將除錯進行下去,直到call指令的時候按F11進行逐陳述句除錯,

會跳轉到這個步驟,
jmp陳述句
這就是call指令的下一條指令,編譯器把呼叫函式之后的下一條指令存放在堆疊上,將來被呼叫函式回傳之后,便可根據這個地址直接執行呼叫函式后需要執行的指令,

在這一點上就可以體現編譯器對函式堆疊幀的呼叫的嚴謹,

既要考慮到如何呼叫函式分配空間,也要考慮到函式呼叫結束怎么回到本該執行的下一條指令,

存放call指令的下一條指令

之后便開始對Add函式堆疊幀的創建,


🧑Add函式堆疊幀的創建

匯編指令
注意第一個操作:

push                 ebp

這里把ebp中存放的值進行壓堆疊,也就是說這個位置存放的是原來ebp所指向的位置,

壓堆疊
這里給出標記: ebp:main

表示的是這里的ebp存放的是main函式堆疊底的位置,將來在pop這個值得時候將會把ebp直接彈回main函式堆疊底的位置,繼而繼續維護main函式,

匯編指令

接下來的操作和開辟main函式堆疊幀十分相似:

mov                   ebp,esp
sub                    esp,0CCh

先將esp指向的位置賦給ebp,這樣ebp就會和esp指向同一個位置,作為即將開辟堆疊幀的堆疊底,

再給esp減去0CCh的值,也就是往上偏移0CCh個位元組長度,十六進制0CCh轉化為十進制為204,這也就是編譯器為Add函式分配的函式堆疊幀的大小,

注: 堆疊幀空間分配是編譯器自行決定的,無法人為估測,

此時ebp到esp之間的部分就是編譯器為Add函式分配的函式堆疊幀,

Add函式堆疊幀


👧Add函式堆疊幀的初始化

和main函式一樣,在函式堆疊幀創建完畢之后,會通過三個暫存器對函式堆疊幀

初始化,這里再次把暫存器作用給大家展示:

暫存器作用

匯編指令
首先進行三個push指令

push              ebx
push              esi
push              edi

壓堆疊操作
匯編指令

前面介紹過:

lea:load effective address(加載有效地址)

lea                          edi,[ebp+FFFFFF34h]
move                      ecx,33h
move                      eax,0CCCCCCCCh

指令的意思是:

  1. 將[ebp+FFFFFF34]地址加載到暫存器edi中,
  2. 將33h作為次數放進暫存器ecx中,
  3. 將0CCCCCCCCh作為要初始化為的內容存放在eax中,

而FFFFFF34的二進制序列是:11111111111111111111111100110100

顯然,這是一個負數,所有ebp+FFFFFF34其實他的地址是在減小,所以此時存放的位置其實是可以計算得到的,
得到初始化起始位置

十六進制數33h的十進制形式為51,也就是要重復進行51次值覆寫,

覆寫值為0CCCCCCCCh,
匯編指令

rep stos           dword ptr es:[edi]

最后的指令就是從edi暫存器放的位置開始往下33h次進行值覆寫,覆寫內容為0CCCCCCCCh,

Add函式初始化后

🎈Add函式實作加法運算

匯編指令

mov         dword ptr [edp-8],0

這是開辟臨時變數的步驟,

將0賦給edp-8的位置,也就是給變數z開辟了一塊空間,

創建z變數

匯編指令

mov               eax,dword ptr [ebp+8]

將ebp+8位置的值放進暫存器eax中保存,

可以從圖上看到,ebp+8的位置時從main函式傳過來的實參臨時拷貝中的10,

ebp+8的位置

此時

eax: 10

add                  eax,dword ptr [ebp+0Ch]

這里我們可以計算,0Ch轉換為十進制也就是12,所有ebp+12應該是從當前ebp位置往下數3個格子(因為一個格子是4個位元組),

找到ebp+0Ch的位置:

ebp+0Ch

將這里面的值加到暫存器eax中去:

此時

eax: 30

匯編指令

mov                      dword ptr [ebp-8],eax

把暫存器eax里的值放進[ebp-8]的位置里,

z的值變為30

此時就已經完成了計算功能,

🧨Add函式回傳值實作

函式功能實作之后,就要回傳函式值了,

匯編指令

mov                         eax,dword ptr [ebp-8]

指令:將[ebp-8]地址的值放進eax暫存器,也就是把剛才計算結果30存放進暫存器中,

🎆Add函式堆疊幀的銷毀

pop是出堆疊指令,把堆疊中的值彈出到指定的地方,

pop               edi
pop               esi
pop               ebx

連續三個pop,將之前初始化Add函式是壓堆疊的三個元素彈出,

pop出堆疊
三個元素出堆疊后,Add函式的堆疊幀隨之減少,esp所指向的位置也隨機發生更改,

匯編指令

mov                               esp,ebp

和創建函式堆疊幀時的操作類似,但又不同,將ebp的值賦給esp,
即esp將會直接指向ebp指向的位置,

esp指向ebp所指位置
一旦執行完上面的操作指令,也就意味著esp,ebp兩個暫存器不再維護Add函式堆疊幀了,開辟的空間將全部返還給作業系統,

此時的堆疊幀情況

匯編指令

pop                           ebp

將堆疊頂的元素彈出到ebp位置,

注意看這里的堆疊頂所放元素:堆疊頂所放元素

前文中已經提到過,這里壓堆疊ebp的用途,就是為了在銷毀Add函式之后ebp可以找到main函式堆疊底位置,繼而繼續維護main函式的堆疊幀,

前文概述

所以這條指令將使ebp指向原main函式堆疊底,

此時函式堆疊幀

此時Add函式堆疊幀已全部銷毀,


🎇回傳到main函式指令

接下來esp就指向了00B910E1,

前文提到過,這是call呼叫指令的下一條指令,所以直接回傳到main函式的下一條指令,

彈出指令
現在在反匯編除錯按F10將直接從Add函式跳轉到main函式call指令的下一條指令,

call指令的下一條指令

add                          esp,8

把8加給esp暫存器,讓其向下移動兩個單元格(一個格子4個位元組)

esp向下兩個單元
此時堆疊頂兩個元素就不再被維護,main函式的函式堆疊幀也隨之減少,

匯編指令

mov                           dword ptr [ebp-20h],eax

將eax暫存器里的值賦給ebp-20h位置,eax是我們在Add函式里計算結束后存放的回傳值(30),ebp-20的位置時變數c的地址,

c值修改

至此,Add函式的功能,堆疊幀開辟到結束就全部解釋完畢了,

🍕🍕總結

函式堆疊幀用到匯編語言的知識,用最底層的角度看待函式呼叫的關系,

文章開頭的幾個問題其實在閱讀到這的時候應該都能夠解決了,

請注意:搞清楚函式堆疊幀并不能讓你寫代碼更厲害,刷演算法更牛逼,函式堆疊幀僅僅是類似于修煉內功一樣的存在,理清楚底層的邏輯有助于我們思考一些比較復雜的問題,

例如遞回演算法,用函式堆疊幀的思想就很容易掌握,

最后,別忘了👍點贊👍+?收藏?+👀關注👀走一波~

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/305504.html

標籤:其他

上一篇:C++認知繼承

下一篇:一篇文章帶你由淺入深去感受四種自定義型別的魅力——結構體型別,位段,列舉型別,聯合體(共用體)型別

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more