指针衰减警告 (C26485) 并将 NOTIFYICONDATA 成员变量传递给 _tcscpy_s

Pointer decay warning (C26485) and passing NOTIFYICONDATA member variable to _tcscpy_s

示例代码:

void CMeetingScheduleAssistantDlg::CreateBackupTrayNotification(CString strInfoTitle, CString strInfo, CString strTip)
{
    ::ZeroMemory(&m_sNTD, sizeof(NOTIFYICONDATA));

    m_sNTD.cbSize = sizeof(NOTIFYICONDATA);
    m_sNTD.hWnd = GetSafeHwnd();
    m_sNTD.uID = 0;
    m_sNTD.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO;

    m_sNTD.dwInfoFlags = NIIF_INFO;

    m_sNTD.uCallbackMessage = WM_MSA_BACKUP_NOTIFICATION;
    m_sNTD.uTimeout = 20000; // 20 Seconds
    m_sNTD.hIcon = LoadIcon(AfxGetResourceHandle(),
        MAKEINTRESOURCE(IDR_MAINFRAME));

    _tcscpy_s(m_sNTD.szInfoTitle, gsl::narrow<rsize_t>(strInfoTitle.GetLength()) + 1, (LPCTSTR)strInfoTitle);
    _tcscpy_s(m_sNTD.szInfo, gsl::narrow<rsize_t>(strInfo.GetLength()) + 1, (LPCTSTR)strInfo);
    _tcscpy_s(m_sNTD.szTip, gsl::narrow<rsize_t>(strTip.GetLength()) + 1, (LPCTSTR)strTip);

    Shell_NotifyIcon(NIM_ADD, &m_sNTD);
}

忽略 (LPCTSTR) 转换,因为我添加了全局 pragma 来忽略警告。我的问题与这些行有关:

_tcscpy_s(m_sNTD.szInfoTitle, gsl::narrow<rsize_t>(strInfoTitle.GetLength()) + 1, (LPCTSTR)strInfoTitle);
_tcscpy_s(m_sNTD.szInfo, gsl::narrow<rsize_t>(strInfo.GetLength()) + 1, (LPCTSTR)strInfo);
_tcscpy_s(m_sNTD.szTip, gsl::narrow<rsize_t>(strTip.GetLength()) + 1, (LPCTSTR)strTip);

m_sNTD是一个NOTIFYICONDATA结构:

typedef struct _NOTIFYICONDATAA {
  DWORD cbSize;
  HWND  hWnd;
  UINT  uID;
  UINT  uFlags;
  UINT  uCallbackMessage;
  HICON hIcon;
#if ...
  CHAR  szTip[64];
#else
  CHAR  szTip[128];
#endif
  DWORD dwState;
  DWORD dwStateMask;
  CHAR  szInfo[256];
  union {
    UINT uTimeout;
    UINT uVersion;
  } DUMMYUNIONNAME;
  CHAR  szInfoTitle[64];
  DWORD dwInfoFlags;
  GUID  guidItem;
  HICON hBalloonIcon;
} NOTIFYICONDATAA, *PNOTIFYICONDATAA;

我收到可怕的指针衰减警告 (C26485)。可以看到,有问题的成员变量是:

旁注:不确定 if ... 是关于什么的。另外,我的结构实际上指向一个 NOTIFYICONDATAW 所以成员变量是 WCHAR.

无论如何,我知道我可以通过使用 &varname[0] 来抑制指针衰减警告。但在这种情况下它不起作用:

_tcscpy_s(m_sNTD.&szInfoTitle[0], gsl::narrow<rsize_t>(strInfoTitle.GetLength()) + 1, (LPCTSTR)strInfoTitle);
_tcscpy_s(m_sNTD.&szInfo[0], gsl::narrow<rsize_t>(strInfo.GetLength()) + 1, (LPCTSTR)strInfo);
_tcscpy_s(m_sNTD.&szTip[0], gsl::narrow<rsize_t>(strTip.GetLength()) + 1, (LPCTSTR)strTip);

& 的正确位置是:

_tcscpy_s(&m_sNTD.szInfoTitle[0], gsl::narrow<rsize_t>(strInfoTitle.GetLength()) + 1, (LPCTSTR)strInfoTitle); 
_tcscpy_s(&m_sNTD.szInfo[0], gsl::narrow<rsize_t>(strInfo.GetLength()) + 1, (LPCTSTR)strInfo); 
_tcscpy_s(&m_sNTD.szTip[0], gsl::narrow<rsize_t>(strTip.GetLength()) + 1, (LPCTSTR)strTip); 

但实际上你用错了_tcscpy_s。第二个参数是目标缓冲区大小,而不是源缓冲区。 _s 函数旨在通过检查缓冲区大小 s 安全;撒谎,你就破坏了这种安全的目的。

只需要省略第二个参数,让它推导即可,这样应该也修复了警告(真的修复,不是打压):

_tcscpy_s(m_sNTD.szInfoTitle, (LPCTSTR)strInfoTitle); 
_tcscpy_s(m_sNTD.szInfo, (LPCTSTR)strInfo); 
_tcscpy_s(m_sNTD.szTip, (LPCTSTR)strTip);