溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++中怎么使用RAII防止資源泄露

發(fā)布時(shí)間:2021-07-30 16:15:03 來(lái)源:億速云 閱讀:136 作者:Leah 欄目:大數(shù)據(jù)

C++中怎么使用RAII防止資源泄露,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

Reason(原因)

Leaks are typically unacceptable. Manual resource release is error-prone. RAII ("Resource Acquisition Is Initialization") is the simplest, most systematic way of preventing leaks.

資源泄露通常都是不可接受的。手動(dòng)釋放資源容易引發(fā)錯(cuò)誤。RAII(“資源請(qǐng)求即初始化”)是防止泄露最簡(jiǎn)單,更加系統(tǒng)化的方式。

Example(示例)

void f1(int i)   // Bad: possible leak
{
   int* p = new int[12];
   // ...
   if (i < 17) throw Bad{"in f()", i};
   // ...
}

We could carefully release the resource before the throw:

在拋出異常之前,我們必須小心地釋放資源:

void f2(int i)   // Clumsy and error-prone: explicit release
{
   int* p = new int[12];
   // ...
   if (i < 17) {
       delete[] p;
       throw Bad{"in f()", i};
   }
   // ...
}

This is verbose. In larger code with multiple possible throws explicit releases become repetitive and error-prone.

代碼冗長(zhǎng)。在更大規(guī)模的,存在更多的拋出異常的可能性的代碼中,顯示釋放資源會(huì)更加繁復(fù)和易錯(cuò)。

void f3(int i)   // OK: resource management done by a handle (but see below)
{
   auto p = make_unique<int[]>(12);
   // ...
   if (i < 17) throw Bad{"in f()", i};
   // ...
}

Note that this works even when the throw is implicit because it happened in a called function:

需要注意的是,即使是隱式的拋出動(dòng)作(因?yàn)樗谡{(diào)用的函數(shù)中發(fā)生),這段代碼仍然可以起作用。

void f4(int i)   // OK: resource management done by a handle (but see below)
{
   auto p = make_unique<int[]>(12);
   // ...
   helper(i);   // may throw
   // ...
}

Unless you really need pointer semantics, use a local resource object:

除非你真的需要指針語(yǔ)義,否則使用一個(gè)局部的資源對(duì)象:

void f5(int i)   // OK: resource management done by local object
{
   vector<int> v(12);
   // ...
   helper(i);   // may throw
   // ...
}

That's even simpler and safer, and often more efficient.

這樣更簡(jiǎn)單,更安全,甚至更高效。

Note(注意)

If there is no obvious resource handle and for some reason defining a proper RAII object/handle is infeasible, as a last resort, cleanup actions can be represented by a final_action object.

如果沒(méi)有明顯的資源句柄而且由于某種原因定義適當(dāng)?shù)腞AII對(duì)象/句柄不可行,作為最有手段,可以通過(guò)一個(gè)final_actrion對(duì)象實(shí)現(xiàn)清理動(dòng)作。

Note(注意)

But what do we do if we are writing a program where exceptions cannot be used? First challenge that assumption; there are many anti-exceptions myths around. We know of only a few good reasons:

但是,如果我們?cè)趯懸粋€(gè)程序而無(wú)法使用異常處理時(shí),我們應(yīng)該做什么?首先挑戰(zhàn)這個(gè)假設(shè);存在很多反對(duì)使用異常的神話。我們只知道很少幾個(gè)是正當(dāng)理由:

  • We are on a system so small that the exception support would eat up most of our 2K memory.

  • 你正在工作的系統(tǒng)是如此之小,支持異常會(huì)吃掉最多2K內(nèi)存(都無(wú)法承受)。

  • We are in a hard-real-time system and we don't have tools that guarantee us that an exception is handled within the required time.

  • 我們處在一個(gè)硬實(shí)時(shí)系統(tǒng)中,沒(méi)有工具可以保證異常處理會(huì)在要求的時(shí)間內(nèi)完成。

  • We are in a system with tons of legacy code using lots of pointers in difficult-to-understand ways (in particular without a recognizable ownership strategy) so that exceptions could cause leaks.

  • 我們所處的系統(tǒng)包含成噸的遺留代碼,這些代碼以難以理解的方式大量使用指針(通常沒(méi)有可識(shí)別的所有權(quán)策略),因此異常可能引發(fā)泄露。

  • Our implementation of the C++ exception mechanisms is unreasonably poor (slow, memory consuming, failing to work correctly for dynamically linked libraries, etc.). Complain to your implementation purveyor; if no user complains, no improvement will happen.

  • 正在使用的C++實(shí)現(xiàn),其異常機(jī)制超乎想象的差勁(緩慢,過(guò)多消費(fèi)內(nèi)存,使用動(dòng)態(tài)鏈接庫(kù)時(shí)無(wú)法工作等)。投訴你的提供者;如果沒(méi)有用戶投訴,就不會(huì)發(fā)生改進(jìn)。

  • We get fired if we challenge our manager's ancient wisdom.

  • 如果我們挑戰(zhàn)管理者的老套經(jīng)驗(yàn),就會(huì)被開除。

Only the first of these reasons is fundamental, so whenever possible, use exceptions to implement RAII, or design your RAII objects to never fail. When exceptions cannot be used, simulate RAII. That is, systematically check that objects are valid after construction and still release all resources in the destructor. One strategy is to add a valid() operation to every resource handle:

這些原因中只有第一個(gè)是根本性的,因此只要可能就使用異常來(lái)實(shí)現(xiàn)RAII,或者設(shè)計(jì)自己的RAII對(duì)象來(lái)保證永遠(yuǎn)不失敗。如果無(wú)法使用異常,就模仿RAII的動(dòng)作。即系統(tǒng)化的檢查對(duì)象被構(gòu)建之后的有效性和析構(gòu)時(shí)會(huì)釋放所有資源。一個(gè)策略是為每一個(gè)資源句柄增加一個(gè)valid操作。

void f()
{
   vector<string> vs(100);   // not std::vector: valid() added
   if (!vs.valid()) {
       // handle error or exit
   }

   ifstream fs("foo");   // not std::ifstream: valid() added
   if (!fs.valid()) {
       // handle error or exit
   }

   // ...
} // destructors clean up as usual

關(guān)于C++中怎么使用RAII防止資源泄露問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI