Почему исключение выдается при использовании memcpy при копировании LPBYTE в LPTSTR (буфер обмена)?
У меня есть массив LPBYTE (взятый из файла), и мне нужно скопировать его в LPTSRT (фактически в буфер обмена). Проблема в том, что работа копируется, но нестабильно, иногда выдается исключение (не всегда), и я не понимаю, почему. Код является:
FILE *fConnect = _wfopen(connectFilePath, _T("rb"));
if (!fConnect)
return;
fseek(fConnect, 0, SEEK_END);
lSize = ftell(fConnect);
rewind(fConnect);
LPBYTE lpByte = (LPBYTE) malloc(lSize);
fread(lpByte, 1, lSize, fConnect);
lpByte[lSize] = 0;
fclose(fConnect);
//Copy into clipboard
BOOL openRes = OpenClipboard(NULL);
if (!openRes)
return;
DWORD err = GetLastError();
EmptyClipboard();
HGLOBAL hText;
hText = GlobalAlloc(GMEM_MOVEABLE, (lSize+ sizeof(TCHAR)));
LPTSTR sMem = (TCHAR*)GlobalLock(hText);
memcpy(sMem, lpByte, (lSize + sizeof(TCHAR)));
Последняя строка - это место, где выдается исключение. большое спасибо
4 ответа
Я не говорю, что это причина Ваших проблем, но это может быть или может быть причиной других проблем в будущем.
Если вы выделите память, как это
LPBYTE lpByte = (LPBYTE) malloc(lSize);
Это доступ за пределами выделенного фрагмента памяти:
lpByte[lSize] = 0;
Выделенная память имеет размер lSize
и он содержит форму местоположения &lpByte[0]
в &lpByte[lSize - 1]
включительно.
РЕДАКТИРОВАТЬ:
Как заметил Ганс, memcpy
также обращается к памяти за пределами выделенного блока. Если sizeof(TCHAR)
1, последний прочитанный байт lpByte[lSize]
и если sizeof(TCHAR)
больше 1, байт прошло lpByte[lSize]
также читаются или, по крайней мере, пытались быть.
Я не уверен в том, что вызывает проблемы в вашем коде, но следующий код работает, и все отлично блокируется / копируется (обратите внимание, что ваши операции с буфером обмена могут быть легко закомментированы и не влияют на источник проблемы):
LPBYTE lpByte = (LPBYTE)malloc(512);
lpByte[0] = 'A';
lpByte[1] = 'B';
lpByte[2] = '0';
// OpenClipboard(NULL);
// EmptyClipboard();
HGLOBAL hText;
hText = GlobalAlloc(GMEM_MOVEABLE, 512);
LPTSTR sMem = (TCHAR*)GlobalLock(hText);
memcpy(sMem, lpByte, 512);
Вы можете попытаться установить точки останова в своем коде прямо перед тем, как произойдет исключение (на самом деле это может иметь разные причины)
Работают ли GlobalAlloc или GlobalLock? Вставьте код проверки ошибок и посмотрите, оба должны возвращать ненулевые значения.
_wfopen
это широкоформатная версия fopen
- вы должны передавать это L"...", а не TCHAR. Версия TCHAR _tfopen
(который будет сводиться к одному из fopen
или же _wfopen
) - См.: http://msdn.microsoft.com/en-us/library/yeby3zcb%28VS.80%29.aspx
LPBYTE lpByte = (LPBYTE) malloc(lSize);
Если это C, вам не нужно приводить результат malloc. Лично МС LP*
типы оставляют во рту дурной вкус - я чувствую, что венгерский язык скрывает читабельность кода кому-то, кто хорошо разбирается в... C. Таким образом, я предпочитаю BYTE *
над LPBYTE
, но это не собирается делать или нарушать код.
fread(lpByte, 1, lSize, fConnect);
Проверьте возвращаемое значение.
lpByte[lSize] = 0;
Как уже упоминалось, этот доступ к памяти находится за пределами массива.
if (!openRes)
return;
DWORD err = GetLastError();
- Ты утечка
lpByte
- Ты звонишь
GetLastError()
... в случае успеха?
Следующий,
LPTSTR sMem = (TCHAR*)GlobalLock(hText);
Хотя я предпочитаю не-LP материал, возможно, выбрать один? (Может быть, сделать бросок LPTSTR
?) Опять же, это не должно иметь значения в конце концов. (Это также может относиться к категории "Это - malloc, и ему не нужен бросок".)
memcpy(sMem, lpByte, (lSize + sizeof(TCHAR)));
Как уже упоминалось, этот memcpy также обращается к недействительной памяти. В частности, lpByte
является lSize
долго, но вы делаете это плюс дополнительный sizeof(TCHAR)
,