c++多線程debug

debug demo

命令行查看

ps -eLf|grep cam_det?//查看當前運行的輕量級進程

ps -aux | grep 執行文件??//查看當前運行的進程

ps -aL | grep 執行文件??//查看當前運行的輕量級進程

pstree -p 主線程ID??//查看主線程和新線程的關系

查看線程棧結構

pstack 線程ID

步驟:

gdb test

r

ctrl + c ?#中斷

break row_num thread 9

c

ctrl + c

thread apply 9 next

thread 9

bt ???#顯示棧信息,想看第幾步,就輸入f 幾

f 3 #

info locals #顯示當前調用棧的所有變量

只允許當前一個線程運行

info threads #查看當前線程,帶星號*

thread xxxxx ?#切換線程,如 thread 5

set scheduler-locking on

next

只暫停指定線程,其他線程不影響

all-stop模式改為non-stop模式,即暫停某一線程,不會影響其他線程

gdb 執行文件

set?pagination?off
set?non-stop?on

break test.cpp:91

show?non-stop

run

thread apply thread_serial_num next #單步查看這個線程運行

break

gdb -v 查看版本信息7.0以前不支持non-stop模式

break,tbreak可以根據行號、函數、條件生成斷點。tbreak設置方法與break相同,只不過tbreak只在斷點停一次,過后會自動將斷點刪除,break需要手動控制斷點的刪除和使能。

break 可帶如下參數:

linenum???????????????? 本地行號,即list命令可見的行號

filename:linenum? 制定個文件的行號

function??????????????? 函數,可以是自定義函數也可是庫函數,如open

filename:function? 制定文件中的函數

condtion??????????????? 條件

*address????? 地址,可是函數,變量的地址,此地址可以通過info add命令得到。

例如:

break 10????

break test.c:10

break main

break test.c:main

b 6??????// 表示在程序開始第6行暫停

b +6 ??// 表示在當前暫停位置往后偏移6行,打個斷點

b -6 ??// 表示在當前暫停位置往前偏移6行,打個斷點

b add ??// 表示在程序中函數add開頭處暫停

b test.c:6 ?// 表示在test.c文件的第6行暫停

b test.c:add // 表示在test.c文件中函數add開頭處暫停

break system

break open

如果想在指定的地址設置斷點,比如在main函數的地址出設斷點。

可用info add main 獲得main的地址如0x80484624,然后用break *0x80484624.

條件斷點就是在如上述指定斷點的同時指定進入斷點的條件。

例如:(假如有int 類型變量 index)

break 10 if index == 3

tbreak 12 if index == 5

info break 可列出所有斷點信息

對特定線程打斷點

  • break <linespec> thread <threadno>
  • break <linespec> thread <threadno> if ...

linespec指定了斷點設置在的源程序的行號 threadno指定了線程的ID ID是GDB分配的 可以通過info threads命令來查看正在運行程序中的線程信息 如果不指定thread <threadno>表示斷點設在所有線程上面

調用GDB調試器的方式

未運行的程序

gdb + 可執行程序: gdb ./test

gdb + 源文件: gdb test.c

正在運行的程序

ps -efL | grep 進程名字 ??#查看進程pid

gdb attach 進程PID

調試異常崩潰程序coredump
編譯debug

CMakeLists.txt

SET(CMAKE_BUILD_TYPE?"Debug")

cmake -DCMAKE_BUILD_TYPE=Debug?..

設置core文件大小

終端輸入ulimit -c,若為0,則不會產生對應的coredump,需要進行修改和設置。?

ulimit?-a ?#查看core文件大小, ulimit -c

ulimit -c unlimited #設置core文件無限大

1)臨時修改

在當前終端中輸入?

ulimit? -c?unlimited??

(可以產生coredump且不受大小限制),這種設置僅對當前終端生效。

2)永久生效

sudo vim /etc/profile

ulimit -c unlimited?#?add

source /etc/profile

設置core文件保存路徑
  1. 臨時有效

新建文件夾coredump

echo '/home/xxxxx/coredump/core-%t-%e-%p-%c' > /proc/sys/kernel/core_pattern

2)永久有效

sudo vim?/etc/sysctl.conf
文件尾部增加:

kernel.core_pattern =/home/xxxxx/coredump/core-%t-%e-%p-%c

sudo sysctl -p /etc/sysctl.conf ??# 重新加載內核參數

這樣配置后,產生的 core文件中將帶有崩潰的程序名、以及它的進程ID。

%t:表示核心轉儲的時間。

%e:表示核心轉儲的程序名。

%p 表示產生核心轉儲的進程ID。

%c:表示核心轉儲的大小

gdb調試運行core file

gdb 可執行文件core_file

gdb 定位程序運行位置

where或backtrace

info frame

在gdb中設置斷點,然后運行程序

使用gdb的display命令,可以在每次程序停下來時顯示某個表達式的值。你可以使用display 變量名來監視某個變量的值,或者使用display 函數名來監視某個函數的返回值

常用命令

- info threads:查看線程狀態信息

- thread <thread-id>:切換當前線程

- thread apply [thread-id-list | all] <command>:針對指定線程執行命令

- break <location> thread <thread-id> if <condition>:設置條件斷點,僅對指定線程生效

- set scheduler-locking on/off/step/replay:控制是否鎖定當前線程,如果當前程序被鎖定,恢復程序運行時,只有當前線程可以運行

- set non-stop on:開啟Non-Stop模式,該模式下,一個線程被中斷執行,不會影響其他線程

- set non-stop off:關閉Non-Stop模式,即進入All-Stop模式。該模式下,一個線程被中斷執行,其他所有線程都會被中斷

- interrut -a:中斷所有線程執行

(gdb) info frame // 顯示棧幀信息
(gdb) info registers // 顯示寄存器
(gdb) info args // 顯示參數
(gdb) info locals // 顯示本地變量
(gdb) p argc // print打印變量argc

在gdb調測時就可以使用l(list)命令查看對應源碼了,加上數字可以指定顯示行,也可以加上函數名稱

(gdb) l

(gdb) list + // 后移

(gdb) list - // 前移

(gdb) list 10 // 顯示指定行

(gdb) list main // 顯示指定函數

(gdb) list main.cpp:5 // 顯示指定文件指定行

(gdb) list main.cpp:main // 顯示指定文件指定函數

命令

用法

info threads

顯示當前可調試的所有線程,每個線程有一個GDB為其分配的ID,后面操作線程的時候會用到這個ID 。前面的有*的是當前調試的線程

thread ID

切換但錢的線程為指定ID的線程

break thread_test.c:123 thread all(例:在相應函數的位置設置斷點break pthread_run1)

在所有線程中相應的行上設置斷點

thread apply ID1 ID2 command

讓一個或者多個線程執行GDB命令command

thread apply all command

讓所有被調試線程執行GDB命令command

set scheduler-locking 選項 command

設置線程是以什么方式來執行命令

set scheduler-locking off

不鎖定任何線程,也就是所有線程都執行,這是默認值

set scheduler-locking on

只有當前被調試程序會執行

set scheduler-locking on step

在單步的時候,除了next過一個函數的情況(熟悉情況的人都知道,這其實是一個設置斷點然后continue的行為)以外,只有當前線程會執行

調試過程中常見問題及解決方案

4.1 符號表問題

????????(1)符號表缺失

????????在編譯時未開啟-g選項,導致調試信息未被包含在可執行文件中。解決方法是在編譯時添加-g選項。

????????(2)符號表不匹配

????????源代碼與編譯生成的符號表不匹配,可能是由于源代碼被修改或重新編譯導致。解決方法是確保源代碼與符號表一致,或重新編譯生成新的符號表。

4.2 內存泄漏檢測與定位

????????(1)內存泄漏現象

????????程序在運行過程中不斷占用內存,且無法釋放。這可能是由于動態分配的內存未被正確釋放導致。

????????(2)內存泄漏檢測工具

????????使用Valgrind等內存泄漏檢測工具可以幫助定位內存泄漏問題。這些工具可以檢測出哪些內存塊被分配但未釋放。

????????(2)內存泄漏定位方法

????????通過分析內存泄漏檢測工具的報告,結合源代碼,可以定位到具體的內存泄漏位置。修復方法包括確保在使用完動態分配的內存后及時釋放,以及檢查是否存在野指針等問題。

4.3 段錯誤處理及原因分析

????????(1)段錯誤現象

????????程序在運行過程中突然崩潰,并報告“段錯誤”或“Segmentation fault”。這通常是由于訪問了非法內存地址導致。

????????(2)段錯誤原因分析

????????可能的原因包括解引用空指針、越界訪問數組、非法內存訪問等。通過分析崩潰時的堆棧信息,可以定位到導致段錯誤的代碼位置。

????????(3) 段錯誤處理方法 ???

????????根據段錯誤的原因,采取相應的處理措施。例如,對于解引用空指針的問題,需要確保在使用指針前進行非空檢查;對于越界訪問數組的問題,需要檢查數組索引是否越界,并確保數組長度足夠。

4.4 性能優化建議

????????(1)優化算法

????????針對程序中耗時的算法進行優化,例如使用更高效的算法或數據結構,減少不必要的計算或內存訪問。

????????(2)減少I/O操作

????????減少不必要的文件讀寫或網絡傳輸操作,例如通過緩存數據或使用更高效的數據傳輸方式來提高I/O性能。

????????(3)多線程/并行計算

????????利用多線程或并行計算技術,將程序中的計算任務分配到多個處理器核心上執行,從而提高程序的執行效率。

????????(4)優化編譯器選項

????????調整編譯器的優化選項,例如開啟O2或O3優化級別,可以讓編譯器自動進行代碼優化,提高程序的執行效率。 ?

linux 動態庫

動態庫,不同的設備安裝位置不一樣

動態庫鏈接的路徑,除了系統目錄,還看環境變量LD_LIBRARY_PATH

echo $LD_LIBRARY_PATH

動態庫在鏈接和運行時都需要

靜態庫只在鏈接時用到。

ldd ./執行文件名字 ??#查找該程序所需的動態鏈接庫

man dlopen ?#手動打開動態鏈接庫

find . -name *lib* ?#在當前路徑下查找某個文件

ls -al

readelf -a 1.out

md5sum 1.out a.out #校驗文件是否一樣

多線程示例代碼

多線程調試基礎命令

https://zhuanlan.zhihu.com/p/692414669

設置編譯類型Debug

a.如果使用gcc/g++編譯,需要加入參數“-g"。

b.如果使用cmake編譯,需要在CMakeLists.txt中加入:

SET(CMAKE_BUILD_TYPE "Debug")????//選擇Debug編譯模式

SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb")??

SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")

c. cmake 編譯 參數

終端帶有Debug

查看線程狀態信息?info threads

info threads顯示,當前共有三個線程。以主線程(第一行)為例:1是GDB為主線程分配的ID,接下來0x7ffff7da3740是pthread庫為主線程分配的pthread ID,后面括號中的355298是kernel為主線程分配的thread ID,再后面是該線程被中斷時,代碼正在執行的代碼位置。

可用通過ps命令或者proc文件系統查看確認:

root@ubuntu:~# ps -eT | grep test

?355298 ?355298 pts/9 ???00:00:02 test

?355298 ?355301 pts/9 ???00:00:02 test

?355298 ?355302 pts/9 ???00:00:02 test

root@ubuntu:~# ls /proc/355298/task/

355298 ?355301 ?355302

線程1前面有個星號*,表示當前線程。默認情況下,執行的GDB命令是針對當前線程。比如此時執行bt(backtrace)命令,獲取的是線程1的調用棧:

切換線程?thread

thread 2把線程2切換為當前線程.用info threads查看,星號*已經切到了線程2的前面

針對指定線程執行命令

thread apply [thread-id-list | all] command 可以針對指定線程執行命令

如:

  • thread apply all bt:打印所有線程的調用棧信息
  • thread apply 3 bt:打印線程3的調用棧信息
  • thread apply 2-3 bt:打印線程2和線程3的調用棧信息

針對特定線程設置斷點

在設置斷點時,我們可以選擇讓斷點對所有的線程生效,或只對特定線程生效。命令格式為:

break <location> ?# 在<location>設置斷點,并對所有線程生效

break <location> thread <thread-id> # 在<location>設置斷點,僅對<thread-id>指定的線程生效

break <location> thread <thread-id> if <condition> # 在<location>設置條件斷點斷點,僅對<thread-id>指定的線程生效

比如 break do_stuff thread 2, 這個命令在do_stuff()入口設置斷點,只有thread 2調用這個函數是才會觸發斷點,其他thread調用這個函數不會觸發斷點。

GDB中的其他所有類型的斷點,也支持對特定線程設置斷點,如tbreak、watch等。

控制線程創建和退出信息

  • set print thread-events on/off 設置是否打印線程創建和退出信息,如上面例子中的:

[New Thread 0x7ffff7da2700 (LWP 355301)]

[New Thread 0x7ffff75a1700 (LWP 355302)]

  • 命令縮寫

有時候使用thread apply [thread-id-list | all] command會稍顯繁瑣,GDB貼心的為我們提供了幾種命令縮寫:

taas command 相當于 thread apply all -s command

tfaas command 相當于 thread apply all -s -- frame apply all -s command?

這個命令非常有用。比如,有時我們只記得一個變量或參數的名字,卻忘了或不知道它是在哪個具體的函數中,就可以用這個命令:tfaas p var_name,這個命令會搜索所有線程的調用棧,找到名字為var_name的變量,并打印它的值,如:

(gdb) tfaas p x1

Thread 2 (Thread 0x7ffff7da2700 (LWP 370514) "test"):

#0 ?thread_1 (arg=0x0) at test.c:10

$5 = 432504243

(gdb) tfaas p y2

Thread 3 (Thread 0x7ffff75a1700 (LWP 370515) "test"):

#0 ?thread_2 (arg=0x0) at test.c:18

$6 = 428735002

控制程序執行的兩種模式

  • All-Stop Mode:在該模式下,不管因為什么原因,一個線程被中斷執行,其他所有的線程都會同時被中斷執行。
  • Non-Stop Mode:在該模式下,一個線程被中斷執行,不會影響其他線程的正常執行。

All-Stop mode

在GDB中調試多線程程序,默認處于All-Stop Mode,即只要有一個線程被中斷執行,其他所有的線程都會被中斷執行。

比如,程序在運行時,按Ctrl+C,所有的線程都會被中斷執行,同樣的,當恢復程序執行時,所有的線程都會同時恢復執行。比如執行continue、step、next等命令。

在All-Stop模式下,只要有一個線程由于觸發斷點等原因停止執行,整個進程都會被停下來,這在一定程度上可以保證所有線程狀態的同步,保持數據的一致性。比如,在查看某個可能會被多個線程修改的數據時,不需要擔心在查看的同時被其他線程修改掉。

但是,這也給程序調試帶來了一些困難,比如,無法100%精確地進行單步調試。有時你會發現,在執行step命令之后,程序卻停在了另外一個線程中。

在線程2和線程3都會調用do_stuff(),在do_stuff()設置斷點后,線程2先觸發斷點停在第4行,同時當前線程切換為線程2,然后執行step命令單步執行一條語句,理論上講,線程2執行一條語句應該停在第5行代碼,然而實際上卻是執行完step命令后,線程3觸發了斷點,而此時線程3并未按照step命令的預期執行一行代碼,而是仍然停留在第4行。再次單步執行,線程2卻再次觸發了斷點,說明線程2執行了不止一條語句

為了解決這個問題,GDB提供了set scheduler-locking mode命令,鎖定當前線程。

線程鎖定模式

set scheduler-locking mode

mode 可能是:

  • off:不鎖定任何線程,當恢復程序執行時,所有線程都可以自由執行
  • on:鎖定當前線程,執行continue、step、next、finish等命令時,只有當前線程恢復執行,其余線程仍然處于中斷狀態
  • step:當單步執行時,和on一樣,其余情況和off一樣。簡單來說,就是在這個鎖定模式下執行單步操作,只有當前線程會執行,其他線程仍然處于中斷狀態。而執行其他命令時,如continue、finish等,和off一樣,即所有線程都可以自由執行。
  • replay:在反向調試時和on一樣,其余情況下,和off一樣。后續會有專門文章詳細介紹反向調試。

默認是replay模式,可以通過show scheduler-locking查看當前鎖定模式。

簡單解釋一下:

  • 先在do_stuff()設置斷點,并執行continue恢復程序執行。隨后,線程2觸發斷點,停在第4行代代碼。
  • 此時程序的狀態是:線程2由于觸發斷點,停在第4行;由于在All-Stop模式,所以線程3也被中斷,恰巧也停在第4行
  • 然后執行set scheduler-locking on 鎖定當前線程2。
  • 此時單步執行,線程2停在第5行,而線程3仍然停在第4行。再執行continue,線程2會再次觸發斷點,此時發現線程3仍然停在第4行。

可見,執行set scheduler-locking on開啟鎖定模式之后,無論用什么命令恢復程序執行,只有當前線程2會執行,其余線程一直處于中斷狀態。

不過,同時中斷所有的線程,可能會導致有些程序無法正常運行。比如,有些程序需要有專門的線程實時處理外部的消息或事件等,如果把所有的線程都中斷的話,會由于外部事件得不到及時響應而導致程序異常終止。

這時,就需要用到Non-Stop模式

Non-Stop Mode

在Non-Stop模式下,一個線程被中斷執行,并不會影響到其他線程。比如,一個線程觸發斷點,只有這一個線程會被中斷執行,其余線程不受影響繼續執行。同樣的,在程序運行時,執行Ctrl+C,也只會中斷一個線程。

要開啟Non-Stop模式,需要在程序開始運行前,執行下面兩個命令:

set pagination off

set non-stop on

可以通過下面這個命令關閉Non-Stop模式,即進入All-Stop模式

set non-stop off

查看Non-Stop模式是否開啟:

show non-stop

后臺執行

我們知道,在Shell中執行程序時,后面加一個&符號,可以把程序放在后臺執行。在GDB中你同樣可以在命令后面加一個&符號,這樣就能把命令放在后臺執行。

之所以提供后臺執行的模式,其實就是讓GDB始終可以接收用戶輸入,即便被調試程序正常運行時,仍然可以在GDB中執行命令。這在Non-Stop模式下,有時會非常有用。

前面講過,Non-Stop模式下,按Ctrl+C只會中斷那個接收到SIGINT信號的線程,其他線程不會受到影響繼續運行。但是,有時候,為了盡量保證線程狀態的同步,我們可能想要讓所有的線程同時被中斷或同時恢復運行,這種情況下,就可以通過后臺執行命令的方式來實現。

并不是所有的命令都支持后臺執行,目前支持后臺執行的命令有:continue、run、attach、step、stepi、next、nexti、finish、until

常用命令小結

- info threads:查看線程狀態信息

- thread <thread-id>:切換當前線程

- thread apply [thread-id-list | all] <command>:針對指定線程執行命令

- break <location> thread <thread-id> if <condition>:設置條件斷點,僅對指定線程生效

- set scheduler-locking on/off/step/replay:控制是否鎖定當前線程,如果當前程序被鎖定,恢復程序運行時,只有當前線程可以運行

- set non-stop on:開啟Non-Stop模式,該模式下,一個線程被中斷執行,不會影響其他線程

r ????#run

b 10 ?#在第10行打斷點

- set non-stop off:關閉Non-Stop模式,即進入All-Stop模式。該模式下,一個線程被中斷執行,其他所有線程都會被中斷

- interrut -a:中斷所有線程執行

- command &:后臺執行

interrupt -a命令可以中斷所有線程的執行

continue -a?(c -a)命令可以恢復所有線程的執行

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/83636.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/83636.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/83636.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

10.7 LangChain v0.3架構大升級:模塊化設計+多階段混合檢索,開發效率飆升3倍!

LangChain v0.3 技術生態與未來發展 關鍵詞:LangChain Chains, Agents 架構, Retrieval Strategy, LangGraph, 模塊化設計 3. LangChain 項目:Chains, Agents, Retrieval Strategy LangChain v0.3 通過 Chains-Agents-Retrieval 三位一體的技術棧,構建起完整的大模型應用開…

分布式 ID 生成的五種方法:優缺點與適用場景

0.簡介 在分布式系統中&#xff0c;生成全局唯一的id是一個常見的需求。由于分布式系統的特性&#xff08;多節點&#xff0c;網絡分區&#xff0c;時鐘不同步等&#xff09;&#xff0c;傳統的單機ID生成方式不再適用&#xff0c;所以一些分布式生成方式應運而生&#xff0c;…

基于單片機路燈自動控制儀仿真設計

標題:基于單片機路燈自動控制儀仿真設計 內容:1.摘要 本設計旨在解決傳統路燈控制方式效率低、能耗大的問題&#xff0c;開展了基于單片機的路燈自動控制儀仿真設計。采用單片機作為核心控制單元&#xff0c;結合光照傳感器、時鐘模塊等硬件&#xff0c;運用相關軟件進行編程和…

計算機網絡-MPLS VPN基礎概念

前面幾篇文章我們學習了MPLS的標簽轉發原理&#xff0c;有靜態標簽分發和LDP動態標簽協議&#xff0c;可以實現LSR設備基于標簽實現數據高效轉發。現在開始學習MPLS在企業實際應用的場景-MPLS VPN。 一、MPLS VPN概念 MPLS&#xff08;多協議標簽交換&#xff09;位于TCP/IP協…

LWIP的Socket接口

Socket接口簡介 類似于文件操作的一種網絡連接接口&#xff0c;通常將其稱之為“套接字”。lwIP的Socket接口兼容BSD Socket接口&#xff0c;但只實現完整Socket的部分功能 netconn是對RAW的封裝 Socket是對netconn的封裝 SOCKET結構體 struct sockaddr { u8_t sa_len; /* 長…

windows 安裝gdal實現png轉tif,以及柵格拼接

windows 安裝gdal實現png轉tif&#xff0c;以及柵格拼接 一、安裝gdal 網上有很多安裝gdal的方法&#xff0c;此處通過osgeo4w安裝gdal 1.下載osgeo4w 下載地址 https://trac.osgeo.org/osgeo4w/ 2、安裝osgeo4w exe文件安裝&#xff0c;前面部分很簡單&#xff0c;就不再…

Node.js 源碼概覽

Node.js 是一個基于 Chrome V8 引擎的 JavaScript 運行時環境&#xff0c;它的源碼結構相當龐大且復雜。下面我將為你講解 Node.js 源碼的主要結構和關鍵組成部分。 源碼結構 Node.js 的主要源碼目錄結構如下&#xff1a; node/ ├── lib/ # JavaScript 核心模…

Linux :線程 【生產者消費者模型】

Linux &#xff1a;線程 【生產者消費者模型與信號量】 &#xff08;一&#xff09;生產消費模型1、生產消費模式概念2、生產者消費者之間的關系3、生產者消費者模型優點 &#xff08;二&#xff09;基于BlockingQueue的生產者消費者模型1、基于阻塞隊列模型2、模擬實現基于阻塞…

mac本地docker鏡像上傳指定虛擬機

在Mac本地將Docker鏡像上傳至指定虛擬機的完整步驟 1. 在Mac本地保存Docker鏡像為文件 通過docker save命令將鏡像打包為.tar文件&#xff0c;便于傳輸至虛擬機。 # 示例&#xff1a;保存名為"my_image"的鏡像到當前目錄 docker save -o my_image.tar my_image:ta…

C++跨平臺開發經驗與解決方案

在當今軟件開發領域&#xff0c;跨平臺開發已成為一個重要的需求。C作為一種強大的系統級編程語言&#xff0c;在跨平臺開發中扮演著重要角色。本文將分享在實際項目中的跨平臺開發經驗和解決方案。 1. 構建系統選擇 CMake的優勢 跨平臺兼容性好 支持多種編譯器和IDE 強大…

Void: Cursor 的開源平替

GitHub&#xff1a;https://github.com/voideditor/void 更多AI開源軟件&#xff1a;發現分享好用的AI工具、AI開源軟件、AI模型、AI變現 - 小眾AI Void&#xff0c;這款編輯器號稱是開源的 Cursor 和 GitHub Copilot 替代品&#xff0c;而且完全免費&#xff01; 在你的代碼庫…

基于HTML+JavaScript+CSS實現教學網站

摘要 21世紀是信息化的時代&#xff0c;信息化物品不斷地涌入我們的生活。同時&#xff0c;教育行業也產生了重大變革。傳統的身心教授的模式&#xff0c;正在被替代。互聯網模式的教育開辟了一片新的熱土。 這算是對教育行業的一次重大挑戰。截至目前&#xff0c;眾多教育行…

基于ssm+mysql的高校設備管理系統(含LW+PPT+源碼+系統演示視頻+安裝說明)

系統功能 管理員功能&#xff1a;系統登錄、員工管理、設備管理、設備采購統計、設備報廢統計&#xff1b;用戶角色功能&#xff1a;設備采購管理、設備報廢管理、個人資料管理。 作者&#xff1a;計算機搬磚家 開發技術&#xff1a;SpringBoot、php、Python、小程序、SSM、Vu…

電力桿塔安全監測解決方案

一、方案背景 在臺風、滑坡等自然災害出現時&#xff0c;極易產生倒桿、斷桿、桿塔傾斜、塔基滑動等致使桿塔失穩的狀況&#xff0c;進而引發導線斷線、線路跳閘等事故&#xff0c;給電網的安全穩定運行造成影響。可借助在鐵塔上裝設的傳感器&#xff0c;能夠感知鐵塔的工作狀態…

基于Quicker構建從截圖到公網圖像鏈接獲取的自動化流程

寫在前面&#xff1a;本博客僅作記錄學習之用&#xff0c;部分圖片來自網絡&#xff0c;如需引用請注明出處&#xff0c;同時如有侵犯您的權益&#xff0c;請聯系刪除&#xff01; 文章目錄 前言預備內容轉webp程序PicGo設置Quicker設置視頻演示總結互動致謝參考 前言 在自建博…

Python Requests庫完全指南:從入門到精通

引言 在Python的生態系統中&#xff0c;requests庫以其簡潔優雅的API設計和強大的功能&#xff0c;成為HTTP請求處理領域的標桿工具。無論是數據爬蟲開發、API接口調用&#xff0c;還是自動化測試場景&#xff0c;requests都能將復雜的網絡交互簡化為幾行可讀性極高的代碼。相…

滲透測試核心技術:內網滲透與橫向移動

內網滲透是紅隊行動的關鍵階段,攻擊者通過突破邊界進入內網后,需快速定位域控、橫向移動并維持權限。本節從內網環境搭建、信息收集、橫向移動技巧到權限維持工具,系統講解如何在內網中隱蔽行動并擴大戰果。 1. 內網環境搭建與基礎配置 目標: 模擬真實企業網絡,構建包含…

學習FineBI

FineBI 第一章 FineBI 介紹 1.1. FineBI 概述 FineBI 是帆軟軟件有限公司推出的一款商業智能 &#xff08;Business Intelligence&#xff09; 產品 。 FineBI 是新一代大數據分析的 BI 工具 &#xff0c; 旨在幫助企業的業務人員充分了解和利用他們的數據 。FineBI 憑借強…

CSS 浮動(Float)及其應用

1. 什么是浮動&#xff08;Float&#xff09;&#xff1f; 浮動元素會脫離正常的文檔流&#xff08;Document Flow&#xff09;&#xff0c;并向左或向右移動&#xff0c;直到碰到父元素的邊緣或另一個浮動元素。 基本語法 .float-left {float: left; }.float-right {float:…

二分算法的介紹簡單易懂

目錄 1.概論 2.樸素的二分算法 3.求左端點的二分算法和求右端點的二分算法 4.總結 1.概論 要想了解什么是二分算法&#xff0c;我們就要知道什么是二分算法&#xff0c;二分算法是根據數組的規律&#xff0c;每次查找的數據原來的效率可能要O&#xff08;n&#xff09;,而我…