Почему исключение выдается на использование memcpy при копировании LPBYTE в LPTSTR (буфер обмена)? - PullRequest
0 голосов
/ 05 июня 2010

У меня есть массив 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 ]

3 голосов
/ 05 июня 2010

Я не говорю, что это причина Ваших проблем, но это может быть или может быть причиной других проблем в будущем.

Если Вы выделяете память следующим образом

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] также считываются или, по крайней мере, пытались быть.

1 голос
/ 05 июня 2010

Я не уверен, что вызывает проблемы в вашем коде, но следующий код работает, и все заблокировано / скопировано отлично (обратите внимание, что ваши операции с буфером обмена могут быть легко закомментированы и не имеют влияние на источник проблемы) :

   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);

Вы можете попытаться установить точки останова в своем коде непосредственно перед тем, как исключение произойдет (на самом деле это может иметь разные причины).

0 голосов
/ 08 июня 2010

_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. Лично, типы MS 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).

0 голосов
/ 05 июня 2010

Работают ли GlobalAlloc или GlobalLock? Вставьте код проверки ошибок и посмотрите, оба должны возвращать ненулевые значения.

...