代码分析 C26408——替换InitInstance中的m_pszHelpFilePath变量
Code analysis C26408 — Replacing the m_pszHelpFilePath variable in InitInstance
在我的应用程序的 InitInstance
函数中,我有以下代码来重写 CHM 帮助文档的位置:
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
free((void*)m_pszHelpFilePath);
m_pszHelpFilePath = _tcsdup(strHelp);
一切正常,但它给了我一个代码分析警告:
C26408 Avoid malloc()
and free()
, prefer the nothrow
version of new
with delete
(r.10).
当您查看 m_pszHelpFilePath
的官方文档时,它确实声明:
If you assign a value to m_pszHelpFilePath
, it must be dynamically allocated on the heap. The CWinApp
destructor calls free( )
with this pointer. You many want to use the _tcsdup( )
run-time library function to do the allocating. Also, free the memory associated with the current pointer before assigning a new value.
是否可以重写此代码以避免代码分析警告,或者我必须添加一个 __pragma
?
从技术上讲,您可以利用 new
/ delete
在 Visual C++ 中默认映射到通常的 malloc
/free
的事实,然后继续并更换。可移植性不会受到太大影响,因为 MFC 无论如何都不可移植。当然你可以使用 unique_ptr<TCHAR[]>
而不是直接 new
/ delete
,像这样:
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
std::unique_ptr<TCHAR[]> str_old(m_pszHelpFilePath);
auto str_new = std::make_unique<TCHAR[]>(strHelp.GetLength() + 1);
_tcscpy_s(str_new.get(), strHelp.GetLength() + 1, strHelp.GetString());
m_pszHelpFilePath = str_new.release();
str_old.reset();
为了替换 new
运算符的稳健性,并且为了最少意外原则,您应该保留 free
/ strdup
.
如果您替换其中多个 CWinApp
字符串,建议为它们编写一个函数,以便只有一个地方带有 free
/ strdup
并抑制警告。
您可以(应该?)使用智能指针来包装您重新分配的 m_pszHelpFilePath
缓冲区。然而,虽然这不是微不足道的,但可以毫不费力地完成。
首先,在您的派生应用程序中声明一个适当的 std::unique_ptr
成员 class:
class MyApp : public CWinApp // Presumably
{
// Add this member...
public:
std::unique_ptr<TCHAR[]> spHelpPath;
// ...
};
然后,您将需要修改构建和分配帮助路径的代码,如下所示(我已将您的 C 风格转换为可以说是更好的 C++ 转换):
// First three (almost) lines as before ...
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
free(const_cast<TCHAR *>(m_pszHelpFilePath));
// Next, allocate the shared pointer data and copy the string...
size_t strSize = static_cast<size_t>(strHelp.GetLength() + 1);
spHelpPath std::make_unique<TCHAR[]>(strSize);
_tcscpy_s(spHelpPath.get(), strHelp.GetString()); // Use the "_s" 'safe' version!
// Now, we can use the embedded raw pointer for m_pszHelpFilePath ...
m_pszHelpFilePath = spHelpPath.get();
到目前为止,还不错。当您的应用程序对象被销毁时,智能指针中分配的数据将自动释放,并且代码分析警告应该消失。但是,我们需要进行最后一项修改,以防止 MFC 框架尝试释放我们分配的 m_pszHelpFilePath
指针。这可以通过在 MyApp
class 覆盖 ExitInstance
:
中将其设置为 nullptr
来完成
int MyApp::ExitInstance()
{
// <your other exit-time code>
m_pszHelpFilePath = nullptr;
return CWinApp::ExitInstance(); // Call base class
}
但是,这可能看起来无事生非,正如其他人所说,您可能有理由简单地取消警告。
在我的应用程序的 InitInstance
函数中,我有以下代码来重写 CHM 帮助文档的位置:
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
free((void*)m_pszHelpFilePath);
m_pszHelpFilePath = _tcsdup(strHelp);
一切正常,但它给了我一个代码分析警告:
C26408 Avoid
malloc()
andfree()
, prefer thenothrow
version ofnew
withdelete
(r.10).
当您查看 m_pszHelpFilePath
的官方文档时,它确实声明:
If you assign a value to
m_pszHelpFilePath
, it must be dynamically allocated on the heap. TheCWinApp
destructor callsfree( )
with this pointer. You many want to use the_tcsdup( )
run-time library function to do the allocating. Also, free the memory associated with the current pointer before assigning a new value.
是否可以重写此代码以避免代码分析警告,或者我必须添加一个 __pragma
?
从技术上讲,您可以利用 new
/ delete
在 Visual C++ 中默认映射到通常的 malloc
/free
的事实,然后继续并更换。可移植性不会受到太大影响,因为 MFC 无论如何都不可移植。当然你可以使用 unique_ptr<TCHAR[]>
而不是直接 new
/ delete
,像这样:
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
std::unique_ptr<TCHAR[]> str_old(m_pszHelpFilePath);
auto str_new = std::make_unique<TCHAR[]>(strHelp.GetLength() + 1);
_tcscpy_s(str_new.get(), strHelp.GetLength() + 1, strHelp.GetString());
m_pszHelpFilePath = str_new.release();
str_old.reset();
为了替换 new
运算符的稳健性,并且为了最少意外原则,您应该保留 free
/ strdup
.
如果您替换其中多个 CWinApp
字符串,建议为它们编写一个函数,以便只有一个地方带有 free
/ strdup
并抑制警告。
您可以(应该?)使用智能指针来包装您重新分配的 m_pszHelpFilePath
缓冲区。然而,虽然这不是微不足道的,但可以毫不费力地完成。
首先,在您的派生应用程序中声明一个适当的 std::unique_ptr
成员 class:
class MyApp : public CWinApp // Presumably
{
// Add this member...
public:
std::unique_ptr<TCHAR[]> spHelpPath;
// ...
};
然后,您将需要修改构建和分配帮助路径的代码,如下所示(我已将您的 C 风格转换为可以说是更好的 C++ 转换):
// First three (almost) lines as before ...
CString strHelp = GetProgramPath();
strHelp += _T("MeetSchedAssist.CHM");
free(const_cast<TCHAR *>(m_pszHelpFilePath));
// Next, allocate the shared pointer data and copy the string...
size_t strSize = static_cast<size_t>(strHelp.GetLength() + 1);
spHelpPath std::make_unique<TCHAR[]>(strSize);
_tcscpy_s(spHelpPath.get(), strHelp.GetString()); // Use the "_s" 'safe' version!
// Now, we can use the embedded raw pointer for m_pszHelpFilePath ...
m_pszHelpFilePath = spHelpPath.get();
到目前为止,还不错。当您的应用程序对象被销毁时,智能指针中分配的数据将自动释放,并且代码分析警告应该消失。但是,我们需要进行最后一项修改,以防止 MFC 框架尝试释放我们分配的 m_pszHelpFilePath
指针。这可以通过在 MyApp
class 覆盖 ExitInstance
:
nullptr
来完成
int MyApp::ExitInstance()
{
// <your other exit-time code>
m_pszHelpFilePath = nullptr;
return CWinApp::ExitInstance(); // Call base class
}
但是,这可能看起来无事生非,正如其他人所说,您可能有理由简单地取消警告。