![](/img/trans.png)
[英]How to create a std::shared_ptr without violating MISRA C++ 2008 Advisory Rule 14-8-2?
[英]How to use std::transform without violating MISRA C++ 2008 Advisory Rule 5-2-10?
我在PC-Lint(au-misra-cpp.lnt)中得到以下錯誤:
ConverterUtil.cpp(90):錯誤864 :(信息-涉及變量'transformValue'的表達式可能取決於求值順序[ MISRA C ++規則5-2-10 ])
ConverterUtil.cpp(90):錯誤864 :(信息-涉及變量'transformValue'的表達式可能取決於求值順序[ MISRA C ++規則5-2-10 ])
ConverterUtil.cpp(90):錯誤534:(警告-忽略函數'std :: transform(std :: _ String_iterator >>,std :: _ String_iterator >>,std :: _ String_iterator >>,int(*)的返回值(int))'(與998行比較,文件C:\\ Program Files(x86)\\ Microsoft Visual Studio 11.0 \\ VC \\ include \\ algorithm)[MISRA C ++規則0-1-7和8-4-6],[ MISRA C ++規則0-3-2])
在此代碼上:
/**Conversion from std::string to bool*/
bool ConverterUtil::ConvertStdStringToBool(const std::string value)
{
std::string transformValue = value;
bool retValue = false;
std::transform(transformValue.begin(), transformValue.end(), transformValue.begin(), &::tolower);
if(transformValue == std::string(static_cast<const char *>("true")))
{
retValue = true;
}
return retValue;
}
我猜想它不喜歡我在轉換中使用相同的std :: string作為輸入和輸出的事實,但是使用另一個字符串作為輸出會產生相同的錯誤。
是否可以使std :: transform MISRA兼容?
我只是在這里猜測(如果不能解決您的問題,我可能會刪除答案)。
嘗試用以下兩個替換包含std::transform
的行:
auto dest = transformValue.begin();
std::transform(transformValue.cbegin(), transformValue.cend(), dest, &::tolower);
注意使用cbegin()
和cend()
而不是begin()
和end()
關於另一個主題 :當您一次只能將傳遞給ConvertStdStringToBool
的字符串復制兩次時。 為此,請替換:
bool ConverterUtil::ConvertStdStringToBool(const std::string value)
{
std::string transformValue = value;
與
bool ConverterUtil::ConvertStdStringToBool(std::string transformValue)
{
(您可能希望在此更改后將transformValue
重命名為value
)。
更新:我的解釋為什么我認為這會有所幫助。
首先,請注意transformValue
是非const
。 因此, transformValue.begin()
和transformValue.end()
將調用以下重載:
iterator begin(); // non const overload
iterator end(); // non const overload
因此,靜態分析器(正確地)得出的結論是begin()
和end()
可能會更改transformValue
的狀態。 在這種情況下, transformValue
的最終狀態可能取決於begin()
和end()
哪個先被調用。
現在,當您調用cbegin()
和cbegin()
cend()
,重載如下:
const_iterator cbegin() const; // notice the const
const_iterator cend() const; // notice the const
在這種情況下,靜態分析器不會推斷出這些調用會更改transformValue
的狀態,並且不會引發問題。 (嚴格來說,即使方法是const
它們也可以更改狀態,因為類中可能存在mutable
數據成員,或者方法可以使用邪惡的const_cast
。恕我直言,不應為此而歸咎於靜態分析器。)
最后說明:電話
std::transform(transformValue.cbegin(), transformValue.cend(), transformValue.cbegin(), &::tolower);
^^^^^^
是錯的。 第三個參數必須是非const
迭代器,即必須是transformValue.begin()
(只有前兩個參數是c*
方法)。
但是,我想,由於上述類似的原因,僅使用transformValue.begin()
作為第三個參數是不夠的,這就是為什么我建議創建另一個變量( dest
)。
這不是一個單獨的答案,更像是對Cassio答案的評論,但是評論太長了。
這是直接將transformValue.begin()
作為第三個參數實際上很容易失敗的方式:在C ++ 03中(不是在11中,但到目前為止GCC尚未切換),允許引用計數的std :: string實現。 libstdc ++有一個。 使用這樣的版本, value
和transformValue
將共享它們的內部緩沖區。
現在,當調用transformValue.begin()
時,可以使用生成的非常量迭代器來修改緩沖區,這很不好,因為它也會更改value
。 因此begin()
必須取消共享緩沖區,即僅為transformValue
分配唯一的緩沖區。 這樣做會使所有現有的迭代器無效 !
因此,在調用的C ++ 98版本cbegin
和cend
:
const std::string& constValue = transformValue;
std::transform(constValue.begin(), constValue.end(),
transformValue.begin(), &::tolower);
你有一個真實的訂單依賴性。 如果begin()
的非const版本在const調用之前被調用,則一切都很好。 但是,如果首先調用const版本(或end()
),則新返回的迭代器將通過非const調用而無效,從而產生未定義的行為。
足夠令人討厭的是,該代碼可能仍然可以工作,因為無效的迭代器將指向舊緩沖區,該緩沖區通過value
保持活動。 由於在大多數情況下會發生這種不共享的情況,因此舊副本的時間將比新副本的時間長,這是一個令人討厭的沉睡者錯誤,直到其中任何一個都不會出現
盡管迭代器begin()和end()在此調用中是恆定的,但檢查器懷疑調用它們會帶來副作用。 因此,根據調用順序,結果可能會有所不同。 我有一個類似的問題,必須通過使用兩個局部變量來關閉檢查器來解決。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.