C++異常詳解

文章目錄

  • 前言
  • 一、回顧C語言
  • 二、異常的概念
  • 三、異常的使用
    • 1.異常的拋出和捕獲
    • 2.異常的重新捕獲
  • 三.異常安全與異常規范
    • 1.異常安全
    • 2.異常規范
  • 四.自定義異常體系
  • 五.C++標準庫的異常體系
  • 六.異常優缺點
  • 練習題
  • 總結


前言

在本篇文章中,我們將會詳細介紹一下有關C++異常的講解,主要涉及異常的使用,應用場景,異常的優缺點等方面,同時有了異常才會引出我們之后學習的一個非常重要的知識點————智能指針。

一、回顧C語言

c語言解決錯誤時一般是通過返回錯誤碼的方式,如果遇到非常嚴重的錯誤,就會終止程序。

🌟 終止程序:比如我們遇到除零錯誤,內存錯誤,空指針的解引用等操作,我們的程序就會終止,程序終止也意味著進程的終止,這有可能會導致大量重要數據的丟失,這是非常嚴重的。
🌟 返回錯誤碼:也可以通過返回錯誤碼的方式告訴我們相應的錯誤,但這只是錯誤碼,我們還需要根據錯誤碼查找相關的錯誤信息,再進一步的分析程序,才能得出具體的錯誤信息,這時很不便利的。很多庫函數都是把錯誤信息放到error中,表示錯誤。

二、異常的概念

我們需要程序告訴是是什么錯誤。

我們C++在解決錯誤時采用的方法時異常

當函數發現了自己無法處理的錯誤時拋異常,讓函數直接或者間接的調用者處理這個異常。

我們將會引入三個關鍵字

🌟 throw:出錯時,用于拋異常(可在任意位置拋出)
🌟 try:里面放可能拋異常的代碼,其中這里的代碼稱為保護代碼,后面跟著catch
🌟 catch:在想要處理的地方,通過異常處理程序捕獲異常,可以有多個catch進行捕獲

throw…………try
{
}
catch(………)
{
}
catch(……)
{
}

其實異常就存在在我們的日常生活中,就比方說微信在網絡不好的時候,會出現一個感嘆號告訴你消息發不出去,此時的程序就是在拋異常,告訴你當前網絡狀態不佳。

如果這個異常按照C語言對錯誤的處理方式進行操作,整個微信進程就會直接崩潰,強行退出。而采用C++的拋異常機制,將拋出的異常捕獲,然后處理,比如當出現網絡不好拋異常時,微信就會采取嘗試多次發送這樣的操作,整個微信程序也不會退出。

正式由于在實際中,很多情況下我們是不希望只要產生異常就直接終止的整個進程的,通過拋異常和捕獲處理異常的手段便可讓程序保持運行。

三、異常的使用

1.異常的拋出和捕獲

異常的拋出和匹配原則

🌟異常通過拋出對象引發,這個對象與catch中()中類型進行匹配,這個對象可以是內置類型,也可以是自定義類型。


#include <iostream>
using namespace std;
double  Division(int x, int y)
{//除零錯誤,拋異常if (y == 0){throw "Division by zero condition!";}else{return ((double)x / (double)y);}
}void fun()
{int a;int b;cin >> a >> b;cout << Division(a, b) << endl;
}
int main()
{try{fun();}catch (const char*errmsy){cout << errmsy << endl;}return 0;
}

我們運行運行拋異常看一下
在這里插入圖片描述
我們確實捕捉到了,打印的就是throw拋的內容。

🌟 我們再匹配相應的catch代碼時,如果有多個都滿足,選取與throw類型匹配且距離較近的catch.

調用鏈是指函數棧幀建立的先后順序,就比如下面代碼中main函數優先建立棧幀,然后func函數建立棧幀,最后division函數建立棧幀,這樣的順序就叫調用鏈。

舉個例子說明一下

#include <iostream>
using namespace std;
double  Division()
{int a;int b;cin >> a >> b;if (b == 0){throw "Division by zero condition!";}else{return ((double)a / (double)b);}
}void fun()
{try{Division();}catch (const char* errmsy){cout <<"void fun()" << errmsy << endl;}
}
int main()
{try{fun();}catch (const char* errmsy){cout <<"int main()" << errmsy << endl;}return 0;
}

main函數調用了fun函數,fun函數調用了Division函數。
main函數中catch與fun函數中的catch都與Division中的throw類型匹配,那么他會調用哪個呢??

我們拋異常來看一下
在這里插入圖片描述
我們發現調用的是fun中的catch,因為兩個都滿足。所以找最近的那一個,就是fun函數了。
🌟拋出異常對象后,會生成一個異常對象的拷貝,并不是直接傳遞給catch()里面的對象,而是將throw對象的拷貝傳給catch()中的對象,這個拷貝的臨時對象會被catch后銷毀。


#include <iostream>
#include <string>
using namespace std;
double  Division(int x, int y)
{//除零錯誤,拋異常if (y == 0){string s("Division by zero condition!");throw s;}else{return ((double)x / (double)y);}
}void fun()
{int a;int b;cin >> a >> b;cout << Division(a, b) << endl;
}
int main()
{try{fun();}catch (const string ret){cout << ret << endl;}return 0;
}

我們拋出的是一個string的臨時對象s,出了作用域銷毀了,如果是直接傳給外邊,傳遞不過去。
如果我們拋異常了,打印的還是Division by zero condition!,就能夠說明生成了拷貝。

我們測試一次看看
在這里插入圖片描述
我們發現確實存在拷貝,這和函數參數的傳遞有異曲同工之妙。

由于臨時對象具有常性,所以當拋出的對象是指針時一定注意在形參上加上const才能被接收。這也解釋了上面的代碼中為什么error_message的類型為什么是const char而不是char
🌟我們一般在catch最后邊加上一個catch(…),表示這個catch可以匹配任意類型,但是不知道異常錯誤是什么。
我們這個東西可以解決很大的問題,如果我們的異常沒有對應的catch,就會報錯,如果放到程序中,就會崩潰。

#include <iostream>
#include <string>
using namespace std;
double  Division(int x, int y)
{//除零錯誤,拋異常if (y == 0){throw "Division by zero condition!";}else if(y==1){return ((double)x / (double)y);}else{throw 1;}
}void fun()
{int a;int b;cin >> a >> b;cout << Division(a, b) << endl;
}
int main()
{try{fun();}catch (const string ret){cout << ret << endl;}catch (...){cout << "Unkown error" << endl;}return 0;
}

我們如果輸入的第二個數為10,就會拋異常,類型為整形,但是外邊沒有對應的類型匹配,就會匹配到(…)中。
在這里插入圖片描述
🌟有一種特殊情況,不用類型匹配:可以拋出子類對象,使用父類對象再catch中進行捕獲,這個在實際中是非常有用的。

在函數調用鏈中異常棧展開匹配原則

🌟1.查看throw是否在try中,如果在,就進行異常捕獲。
🌟2.如果存在匹配的catch,就調到對應的catch進行處理。
🌟3.如果這一層沒有匹配的catch,退出當前棧,就到上一層中進行尋找。
🌟4.如果再main函數中,也不存在匹配的catch就報錯,
沿著調用鏈查找匹配catch子句的過程稱為棧展開。
🌟5.異常捕獲與exit不同。exit直接退出程序,catch處理完異常之后,catch后面的代碼會正常執行。

#include <iostream>
#include <string>
using namespace std;
double  Division(int x, int y)
{//除零錯誤,拋異常if (y == 0){throw "Division by zero condition!";}else if (y == 1){return ((double)x / (double)y);}
}void fun()
{int a;int b;cin >> a >> b;cout << Division(a, b) << endl;
}
int main()
{try{fun();}catch (const string ret){cout << ret << endl;}catch (...){cout << "Unkown error" << endl;}cout << "異常處理后繼續執行相關代碼" << endl;return 0;
}

在這里插入圖片描述

2.異常的重新捕獲

有可能單個的catch不能完全處理一個異常,在進行一些校正處理以后,希望再交給更外層的調用
鏈函數來處理,catch則可以通過重新拋出將異常傳遞給更上層的函數進行處理。

我們捕獲這個異常并不是為了處理這個異常,而是為了干一些其他的事情之后,再把這個異常拋給上層,繼續處理。

我們舉一個例子理解一下


#include <iostream>
#include <string>
using namespace std;
double  Division(int x, int y)
{//除零錯誤,拋異常if (y == 0){throw "Division by zero condition!";}else{return ((double)x / (double)y);}
}void fun()
{int*p = new int[10];int a;int b;cin >> a >> b;cout << Division(a, b) << endl;cout << "delete[] p" << endl;delete[] p;
}
int main()
{try{fun();}catch (const string ret){cout << ret << endl;}catch (...){cout << "Unkown error" << endl;}return 0;
}

在fun函數中new了一塊空間,現在拋異常看一下


我們new的空間并沒有被釋放,發生了內存泄漏

這時就需要用到異常的重新捕獲了,我們需要在fun函數中對這個異常進行一次捕獲,釋放new的空間,再拋給main函數。
為我們也可以直接在fun中捕獲異常,不在main中處理呀??
而在我們對異常進行一部分操作時,我們更愿意讓所有異常在main函數中進行統一處理,比如對異常進行記錄日志這樣的操作,此時需要重新使用throw拋出異常。

我們看一下解決代碼

#include <iostream>
#include <string>
using namespace std;
double  Division(int x, int y)
{//除零錯誤,拋異常if (y == 0){throw "Division by zero condition!";}else{return ((double)x / (double)y);}
}void fun()
{int*p = new int[10];int a;int b;cin >> a >> b;try{cout << Division(a, b) << endl;}catch (...){cout << "delete[] p" << endl;delete[] p;throw;//捕到什么拋什么}cout << "delete[] p" << endl;delete[] p;
}
int main()
{try{fun();}catch (const string ret){cout << ret << endl;}catch (...){cout << "Unkown error" << endl;}return 0;
}

運行看一下
在這里插入圖片描述

一旦catch捕獲異常,不能將異常用throw語句再次拋出,這句話是不對的。

三.異常安全與異常規范

1.異常安全

🌟構造函數時用來構造對象和初始化的,最好不要在構造函數拋異常,可能會導致對象不完整或者沒有完全初始化。

🌟析構函數是用來釋放空間的,對資源進行清理。最好不要在析構函數拋異常,可能會導致資源泄露(內存泄漏,句柄未關閉)。
🌟C++中異常經常會導致資源泄露問題,比如在new和delete中拋異常,導致內存泄漏,在lock和unlock之間拋出異常1導致死鎖等問題,我們將會用智能指針來解決這個問題。

2.異常規范

我們在書寫異常時,可以拋出任意類型的對象, 異常規格說明的目的是為了讓函數使用者知道該函數可能拋出的異常有哪些。

C++98,建議,并不會強制報錯,如果我們不這樣做了只會有警告,這個是為了兼容c語言做出的讓步。

🌟我們可以在函數頭后買你加上throw( ),括號里存放可能拋出的異常類型。
throw(char,int char*)就表明了這個函數可能拋出char,int,char這三種類型的異常。
🌟這里表示這個函數只會拋出bad_alloc的異常
void
operator new (std::size_t size) throw (std::bad_alloc);
🌟throw(),表明這個函數只會不會拋出異常
🌟如果無異常接口聲明,此函數可以拋任意類型的異常

但是有些異常類型是非常復雜的,為了寫出可能發生的異常類型,代價會很大,而且寫時太繁瑣寫出來也不美觀。因此,這個建議性的規范很少有人用,也正因為它只是一個建議,所以不使用或者不按要求使用也不會報錯。

#include <iostream>
#include <string>
using namespace std;
double  Division(int x, int y) throw()//表明不會拋異常
{//除零錯誤,拋異常if (y == 0){throw "Division by zero condition!";}else{return ((double)x / (double)y);}
}void fun()
{int a;int b;cin >> a >> b;cout << Division(a,b) << endl; 
}
int main()
{try{fun();}catch (const string ret){cout << ret << endl;}catch (...){cout << "Unkown error" << endl;}return 0;
}

但是如果我們硬要拋異常呢??
在這里插入圖片描述
只會存在警告,不會強制報錯。

C++11

🌟noexcept,表明函數不會拋異常
但如果我們還是硬拋異常會怎樣呢???

在這里插入圖片描述
代碼就給我們直接掛掉了。

四.自定義異常體系

在以后寫代碼的時候會遇到小組合作的形式,每個小組負責不同的模塊,每個小組都會拋出異常,但是每個小組拋出的異常類型不同,放在一起在main函數中進行捕捉就會很復雜。
實際中拋出和捕獲的匹配原則有一個例外,類型可以不完全匹配,拋出子類對象用父類進行捕捉。每個小組都可以拋出派生類的異常,在mian函數中使用基類統一捕捉。

實際項目中,可以創建一個父類,父類中有一個錯誤碼(int)和錯誤描述信息(string),在這個類里面創建一個虛函數用于返回內部的string對象方便使用人員打印。

class Exception
{
public:Exception(const string& errmsg, int id):_errmsg(errmsg), _id(id){}virtual string what() const{return _errmsg;}
protected:string _errmsg;int _id;
};

不同的小組拋出的異常都會具有本小組的特點,用繼承的方式創建一個類,子類中添加一個成員變量記錄當前模塊的特殊錯誤信息,并且該類所對應的what函數就可以通過重寫來添加一個標志性內容,我們就可以更加容易的知道哪里出了問題。

class SqlException : public Exception
{
public:SqlException(const string& errmsg, int id, const string& sql):Exception(errmsg, id), _sql(sql){}virtual string what() const{string str = "SqlException:";str += _errmsg;str += "->";str += _sql;return str;}
private:const string _sql;
};
class CacheException : public Exception
{
public:CacheException(const string& errmsg, int id):Exception(errmsg, id){}virtual string what() const{string str = "CacheException:";str += _errmsg;return str;}
};
class HttpServerException : public Exception
{
public:HttpServerException(const string& errmsg, int id, const string& type):Exception(errmsg, id), _type(type){}virtual string what() const{string str = "HttpServerException:";str += _type;str += ":";str += _errmsg;return str;}
private:const string _type;
};

那么有了這些描述異常的父子類之后就可以用下面的代碼來測試異常:

void SQLMgr()
{srand(time(0));if (rand() % 7 == 0){throw SqlException("權限不足", 100, "select * from name = '張三'");}//throw "xxxxxx";
}
void CacheMgr()
{srand(time(0));if (rand() % 5 == 0){throw CacheException("權限不足", 100);}else if (rand() % 6 == 0){throw CacheException("數據不存在", 101);}SQLMgr();
}
void HttpServer()
{// ...srand(time(0));if (rand() % 3 == 0){throw HttpServerException("請求資源不存在", 100, "get");}else if (rand() % 4 == 0){throw HttpServerException("權限不足", 101, "post");}CacheMgr();
}
int main()
{while (1){this_thread::sleep_for(chrono::seconds(1));try {HttpServer();}catch (const Exception& e) // 這里捕獲父類對象就可以{// 多態cout << e.what() << endl;}catch (...){cout << "Unkown Exception" << endl;}}return 0;
}

main函數中首先調用httpserver函數,生成一個隨機數,我們把這個數字看作一種情況,如果這個數字能被3 和4整除那么這種情況就出錯了,直接使用throw來拋出異常,如果沒有出錯的花就調用緩沖區的函數,這個函數里面也是相同道理,在這個函數之后就調用數據庫的相關函數遇到一些情況就拋出異常,那么在main函數里面我們就可以統一使用父類類型的catch來統一捕獲異常,并使用里面的what函數來打印出從的內容,那么上面的代碼運行的結果如下:

五.C++標準庫的異常體系

C++ 提供了一系列標準的異常,定義在 中,我們可以在程序中使用這些標準的異常。它們是以父
子類層次結構組織起來的,如下所示:

在這里插入圖片描述

在這里插入圖片描述
由于C++提供的異常體系對項目開發中的異常幫助十分有限,所以這個標準幾乎沒人用。’

六.異常優缺點

優點

🌟1.相比于錯誤碼,異常可以清晰準確的展現出錯誤信息,甚至包含堆棧調用的信息,幫助我們更好的定位bug
🌟2.異常會進行多層跳轉,不用層層返回進行判斷,直到最外層拿到錯誤。


int ConnnectSql()
{// 用戶名密碼錯誤if (...)return 1;// 權限不足if (...)return 2;
}int ServerStart() {if (int ret = ConnnectSql() < 0)return ret;int fd = socket()if(fd < 0return errno;
}int main()
{if (ServerStart() < 0)...return 0;
}

下面這段偽代碼我們可以看到ConnnectSql中出錯了,先返回給ServerStart,ServerStart再返回給main函數,main函數再針對問題處理具體的錯誤。

如果是異常體系,不管是ConnnectSql還是ServerStart及調用函數出錯,都不用檢查,因為拋出的異常異常會直接跳到main函數中catch捕獲的地方,main函數直接處理錯誤。
🌟2.很多的第三方庫都包含異常,比如boost、gtest、gmock等等常用的庫,那么我們使用它們也需要使用異常
🌟4.部分函數使用異常更好處理。
T& operator這樣的函數,如果pos越界了只能使用異常或者終止程序處理,沒辦法通過返回值表示錯誤

缺點:

🌟1.導致執行流亂跳,導致我們追蹤調式以及分析程序時,比較困難。
🌟2.異常會有一些性能的開銷,。當然在現代硬件速度很快的情況下,這個影響基本忽略不計。
🌟3.C++沒有垃圾回收機制,資源需要自己管理,有可能發生內存泄漏,死鎖等安全問題。
🌟4.C++標準庫的異常體系定義得不好,導致大家各自定義各自的異常體系,非常的混亂。
🌟異常盡量規范使用,否則后果不堪設想,隨意拋異常,外層捕獲的用戶苦不堪言。

練習題

如何捕獲異常可以使得代碼通過編譯? ()

class A

{
public:
??A(){}
};

void foo()
{? throw new A; }

A.catch (A x)
B.catch (A * x)
C.catch (A & x)
D.以上都不是

正確答案是B, 異常是按照類型來捕獲的,throw后拋出的是A*類型的異常,因此要按照指針方式進行捕獲

總結

以上就是今天要講的內容,本文僅僅詳細介紹了C++異常的內容。希望對大家的學習有所幫助,僅供參考 如有錯誤請大佬指點我會盡快去改正 歡迎大家來評論~~ 😘 😘 😘

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

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

相關文章

微服務架構:注冊中心 Eureka、ZooKeeper、Consul、Nacos的選型對比詳解

微服務架構&#xff08;Microservices Architecture&#xff09;是一種基于服務拆分的分布式架構模式&#xff0c;旨在將復雜的單體應用程序拆分為一組更小、更獨立的服務單元。這些服務單元可以獨立開發、測試、部署&#xff0c;并使用不同的技術棧和編程語言。它們通過輕量級…

[華為OD] C卷 dfs 特殊加密算法 100

題目&#xff1a; 有一種特殊的加密算法&#xff0c;明文為一段數字串&#xff0c;經過密碼本查找轉換&#xff0c;生成另一段密文數字串。 規則如下 1?明文為一段數字串由0-9組成 2.密碼本為數字0-9組成的二維數組 3?需要按明文串的數字順序在密碼本里找到同樣的數字串…

PUBG非升級實用槍皮-部分盤點

藏匿處的黑貨箱武器需要耗費高額成本才能升級 對于像我這樣的日常休閑玩家來說是一筆不小的&#xff08;巨大的&#xff01;&#xff09;負擔 其實有許多普通非升級槍皮也是不錯的選擇 今天就來盤點一下我自己日常在用的普通皮 來看看你是不是也在用一樣的 &#xff08;僅是盤點…

【OceanBase診斷調優】—— 租戶資源統計項及其查詢方法

本文主要介紹 OceanBase 數據庫中租戶資源統計項及其查詢方法。 適用版本 OceanBase 數據庫 V4.1.x、V4.2.x 版本。 CPU 資源統計項 邏輯 CPU 使用率&#xff08;線程處理請求的時間占比&#xff09;。 通過虛擬表 __all_virtual_sysstat 在 SYS 系統租戶下&#xff0c;查看…

AtCoder Beginner Contest 308 A題 New Scheme

A題&#xff1a;New Scheme 標簽&#xff1a;模擬 題意&#xff1a;給定 8 8 8個數的序列&#xff0c;詢問這些數是否滿足以下條件&#xff1a; 在 100 100 100到 675 675 675之間且能被 25 25 25整除序列是單調非遞減的 題解&#xff1a;按題意模擬判斷就好了。 代碼&#…

09.zabbix自定義模塊并使用

zabbix自定義模塊并使用 根據tcp的11中狀態獲取值&#xff0c;進行批量配置監控項 [rootyunlong66 ~]# cat /etc/zabbix/zabbix_agentd.d/tcp.conf UserParameterESTABLISHED,netstat -antp |grep -c ESTABLISHED UserParameterSYN_SENT,netstat -antp |grep -c SYN_SENT Use…

Obsidian/Typora設置圖床

在obsidian中默認圖片是保存在本地的&#xff0c;但是在要導出文檔上傳到網上時&#xff0c;由于圖片保存在本地&#xff0c;會出現無法加載圖片的問題。 這里引用的一段話&#xff1a; 這里使用picgo-core和gitee實現圖床功能&#xff0c; 參考1&#xff1a; Ubuntu下PicGO配…

Github學習

1.Git與Github 區別: Git是一個分布式版本控制系統&#xff0c;簡單的說就是一個軟件&#xff0c;用于記錄一個或若干個文件內容變化&#xff0c;以便將來查閱特點版本修訂情況的軟件。 Github是一個為用戶提高Git服務的網站&#xff0c;簡單說就是一個可以放代碼的地方。Gi…

C語言 | Leetcode C語言題解之第85題最大矩形

題目&#xff1a; 題解&#xff1a; int maximalRectangle(char** matrix, int matrixSize, int* matrixColSize) {int m matrixSize;if (m 0) {return 0;}int n matrixColSize[0];int left[m][n];memset(left, 0, sizeof(left));for (int i 0; i < m; i) {for (int j …

SeetaFace6人臉活體檢測C++代碼實現Demo

SeetaFace6包含人臉識別的基本能力&#xff1a;人臉檢測、關鍵點定位、人臉識別&#xff0c;同時增加了活體檢測、質量評估、年齡性別估計&#xff0c;并且順應實際應用需求&#xff0c;開放口罩檢測以及口罩佩戴場景下的人臉識別模型。 官網地址&#xff1a;https://github.co…

【補充】圖神經網絡前傳——DeepWalk

論文閱讀 論文&#xff1a;https://arxiv.org/pdf/1403.6652 參考&#xff1a;【論文逐句精讀】DeepWalk&#xff0c;隨機游走實現圖向量嵌入&#xff0c;自然語言處理與圖的首次融合_隨機游走圖嵌入-CSDN博客 abstract DeepWalk是干什么的&#xff1a;在一個網絡中學習頂點…

【Mac】Ghost Buster Pro(蘋果電腦內存清理專家) v3.2.5安裝教程

軟件介紹 Ghost Buster pro是一款針對Mac系統的電腦清理和優化工具&#xff0c;可以幫助用戶清理系統垃圾、修復注冊表錯誤、卸載不需要的軟件、管理啟動項等&#xff0c;從而提高系統性能和穩定性。 安裝教程 1.打開鏡像包&#xff0c;拖動「Ghost Buster Pro」到應用程序中…

GIT SSL certificate problem

簡單來說&#xff0c;SSL 協議可以為你的 Web 瀏覽器或其他進程提供一種安全的通道&#xff0c;使服務器和客戶端之間的數據傳輸過程不被第三方竊取或篡改。這非常重要&#xff0c;特別是在處理敏感數據&#xff0c;比如信用卡信息、用戶名和密碼等情況下。 現在&#xff0c;S…

Flutter 中的 Row 小部件:全面指南

Flutter 中的 Row 小部件&#xff1a;全面指南 在 Flutter 中&#xff0c;Row 是一個水平布局的小部件&#xff0c;用于將子控件沿著水平軸排列。Row 類似于 HTML 中的 div 標簽&#xff0c;但僅限于水平布局。它非常適合用來創建行式布局&#xff0c;如表單輸入、按鈕組、標簽…

【linux軟件基礎知識】完全公平調度

完全公平調度&#xff08;CFS&#xff09; CFS根據每個進程相對于所有可運行線程總權重的權重為每個進程分配一個“時間片”。 CFS 的目標是近似“無限小”的調度持續時間&#xff0c;稱為目標延遲。 較小的目標延遲可以提高交互性并接近完美的多任務處理&#xff0c;但其代價…

【Linux網絡】Https【下】{CA認證/證書的簽發與認證/安全性/總結}

文章目錄 1.引入證書【為方案五鋪墊】1.1再談https1.2SSL/TLS1.3CA機構1.4理解數字簽名1.4繼續鋪墊1.5方案五服務端申請證書回顧一二三回顧方案四方案五過程尋找方案五的漏洞客?端對證書進?認證 2.查看證書2.1查看瀏覽器的受信任證書發布機構2.2中間?有沒有可能篡改該證書2.…

差分約束 C++ 算法例題

差分約束 差分約束 是一種特殊的 n 元一次不等式組&#xff0c;m 個約束條件&#xff0c;可以組成形如下的格式&#xff1a; { x 1 ? x 1 ′ ≤ y 1 x 2 ? x 2 ′ ≤ y 2 ? x m ? x m ′ ≤ y m \begin{cases} x_1-x_1^{} \le y_1 \\ x_2-x_2^{} \le y_2 \\ \cdots \\ x_…

數據庫的要求

本來我是不準備寫數據庫的。而且是準備從零開始&#xff0c;學習python&#xff0c;學完語言學&#xff0c;會c和寫作技法&#xff0c;再來學習數據庫 那樣做的復雜度是天量的&#xff0c;按部就班什么的具備&#xff0c;因為你完全不清楚什么時候就有這個基礎和條件&#xff0…

【53】Camunda8-Zeebe核心引擎-Partitions分區與Internal processing內部處理

Partitions分區 在Zeebe中,所有數據都是基于分區的。(一個)分區本質上是一個關于流程事件的持久化流。在broker集群中,分區分布在節點之間,因此可以將其視為分片。啟動/初始化Zeebe 集群時,用戶可以配置所需的分區數。如果使用過Kafka,這部分內容是比較相似的。 每當部…

SpringBoot集成jxls2實現復雜(多表格)excel導出

核心依賴 需求 導出多個表格&#xff0c;包含圖片&#xff0c;類似商品標簽 1.配置模板 創建一個xlsx的模板文件&#xff0c;配置如下 該模板進行遍歷了兩次&#xff0c;因為我想要導出的數據分為兩列展示&#xff0c;左右布局&#xff0c;一個循環實現不了&#xff0c;所以采…