为什么在将LPBYTE复制到LPTSTR(剪贴板)期间使用memcpy抛出异常?

时间:2010-06-05 00:27:38

标签: c++ memcpy 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 个答案:

答案 0 :(得分:3)

我不是说,这是你的问题的原因,但它可能是或可能是未来其他问题的原因。

如果你像这样分配内存

LPBYTE lpByte = (LPBYTE) malloc(lSize);  

这是在分配的内存块之外的访问:

lpByte[lSize] = 0;

已分配的内存大小为lSize,其中包含&lpByte[0]&lpByte[lSize - 1]的位置。

修改

正如Hans注意到的那样,memcpy也访问分配块之外的内存。如果sizeof(TCHAR)为1,则最后一个读取字节为lpByte[lSize],如果sizeof(TCHAR)大于1,则还会读取或至少尝试过lpByte[lSize]字节。

答案 1 :(得分:1)

我不确定导致代码出现问题的原因,但以下代码可以正常工作,所有内容都已锁定/复制正常(请注意,您的剪贴板操作可以轻松注释掉并具有对问题的来源没有影响)

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

您可以尝试在异常发生之前在代码中设置断点(实际上可能有不同的原因)。

答案 2 :(得分:0)

GlobalAlloc或GlobalLock有效吗?将一些错误检查代码放入并查看,两者都应返回非NULL值。

答案 3 :(得分:0)

_wfopenfopen的宽字符版本 - 你应该将它传递给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*类型在我的口中留下了不好的味道 - 我觉得匈牙利人将代码的可读性模仿给精通...的人。因此,我更喜欢BYTE *而不是LPBYTE 1}},但它不会破坏代码。

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的时间lSizesizeof(TCHAR),但您正在执行此操作并加{{1}}。