使用wcscpy_s的wchar_t数组大小问题

Bog*_*mer 1 c++ clipboard mfc copy wchar-t

我对尺寸问题感到困惑.运行以下代码会在运行时引发异常.具体来说,它似乎在最后出现,文本仍然粘贴成功.由于我的技能有限,我无法清楚地解释这个例外.它开始于我决定使用wcscpy_s函数,因为wcscpy的折旧在我的noob程序中运行良好.

#define _CRT_SECURE_NO_WARNINGS
#include <afxwin.h>

int main() {
    wchar_t wcSource[7] = L"Testeu"; // Throws an exception error. However, wcSource[8] doesn't
    //wchar_t wcSource[9] = L"TestCopy"; // Runs fine

    UINT iSize = sizeof(wcSource);

    if (OpenClipboard(NULL)) {
        EmptyClipboard();
        HGLOBAL hClipboardData;
        hClipboardData = GlobalAlloc(GMEM_DDESHARE, iSize);
        wchar_t *wpchData;
        wpchData = (wchar_t*)GlobalLock(hClipboardData);

        //wcscpy(wpchData, wcSource); // Works fine
        wcscpy_s(wpchData, iSize, wcSource);

        GlobalUnlock(hClipboardData);
        SetClipboardData(CF_UNICODETEXT, hClipboardData);
        CloseClipboard();
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

wcscpy_s()期望一个CHARACTER计数,但你传递的是BYTE计数.在Windows上,sizeof(wchar_t)是2个字节.

对于剪贴板缓冲区分配内存时(这在你的榜样将需要14个字节),你需要一个字节计数,但因为要传递的字节数作为一个字符计数wcscpy_s(),你告诉它的剪贴板缓冲区最多可容纳14 wchar_t元素,实际上它只能容纳7.您wcscpy_s()允许超出剪贴板缓冲区的范围(例如,如果它想要预先填充缓冲区内存,然后填充实际字符). 这样做会破坏调用堆栈,main()退出时很容易导致异常.

您需要传递wcscpy_s()剪贴板缓冲区可以容纳的最大CHARACTER数.不是它可以容纳的最大BYTES数.

你可以做到这一点除以iSize通过sizeof(wchar_t),例如:

wcscpy_s(wpchData, iSize / sizeof(wchar_t), wcSource);
Run Code Online (Sandbox Code Playgroud)

或者,由于正在使用的源阵列的确切字节大小来分配剪贴板缓冲器,则可以使用_countof()以获得阵列中的字符数(不能传递所分配的剪贴板缓冲区_countof()),例如:

wcscpy_s(wpchData, _countof(wcSource), wcSource);
Run Code Online (Sandbox Code Playgroud)

或者,您可以wsclen()改为使用,例如:

wchar_t wcSource[] = L"Testeu";

int iLen = wcslen(wcSource) + 1;
UINT iSize = iLen * sizeof(wchar_t);
...
hClipboardData = GlobalAlloc(GMEM_DDESHARE, iSize);
...
wcscpy_s(wpchData, iLen, wcSource);
Run Code Online (Sandbox Code Playgroud)