【问题标题】:C/C++ strcpy unhandled read violationC/C++ strcpy 未处理的读取冲突
【发布时间】:2012-04-27 05:53:55
【问题描述】:
unsigned char* Data::getAddress(unsigned char* address)
{
    strcpy((char*)address, (char*)this->_address);
    return (unsigned char*)address;
}

int main()
{
    Data d;
    d.makealinkedlisthere();
    while (d)
    {
       unsigned char address[256];
       printf("0x%08x \r\n",d.getAddress(address));
       d = d.getNext();
    }
    return 0;
}

它返回前两个(它们是相同的,并且应该不同[可以从调试器中看出]...)然后崩溃。

它只是创建一个链表。受保护的成员Data* _next ...一连串。

unsigned char* 来自 Windows 函数 VirtualQueryEx,它是它返回的 MEMORY_BASIC_INFORMATION 数据结构的一部分。

this->_address = (unsigned char*)meminfo->BaseAddress; // casted from void*

它是 void*,但我看到它在其他代码中转换为 unsigned char*。在调试器中,我可以看到它表示为十六进制数字。

D1: +    _address   0x7ffd5000 <Bad Ptr>    unsigned char * 
D1->_next:+  _address   0x7f6f0000 "áå•ú`©" unsigned char * 
D1->_next->_next+    _address   0x7ffb0000 " "  unsigned char *

【问题讨论】:

  • 请出示makealinkedlisthere()函数的源码
  • 您没有提供足够的信息。 Data::makealinkedlistthere 是做什么的?
  • 您需要提供有关数据的更多信息,以便我们弄清楚这里发生了什么。特别是makealinkedlistheregetNext。顺便说一句,循环看起来很可疑。
  • 你总是将相同的指针传递给'getAddress'方法,所以它自然总是返回相同的结果:指向'address'数组的第一个字符的指针。它每次都用不同的数据填充该数组,但您的代码不会打印该数据,只打印一个指向它的指针。
  • 但是MEMORY_BASIC_INFORMATION.BaseAddress 不是字符串。你不能像字符串一样复制它!

标签: c++ string char strcpy


【解决方案1】:

MEMORY_BASIC_INFORMATION.Base Address 是页面区域的位置,而不是字符串,并且不能保证它会以空值终止。 从 MSDN 站点您可以看到 MEMORY_BASIC_INFORMATION structure

typedef struct _MEMORY_BASIC_INFORMATION {
  PVOID  BaseAddress;
  PVOID  AllocationBase;
  DWORD  AllocationProtect;
  SIZE_T RegionSize;
  DWORD  State;
  DWORD  Protect;
  DWORD  Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

要复制数据,您应该使用大小 = 255 的memcpy

回看你的代码,只要没有其他问题,改成

PVOID Data::getAddress(PVOID address,size) {    
    memcpy((address, (void *)this->_address, size);
    address[size]=NULL;
    return address;
}
int main() {
    Data d;
    d.makealinkedlisthere();
    while (d) {
       unsigned char address[256];
       printf("Address: 0x%08x \n",d.getAddress((PVOID)address),sizeof(address));
       printf("Data: %s\n",(LPSTR)d.getAddress((PVOID)address),sizeof(address));
       d = d.getNext();
    }
    return 0;
}

应该有效

还请注意,存储RegionSize 并在memcpy 之前进行边界检查是安全的。

【讨论】:

  • OP 实际上只使用 BaseAddress,而不是整个 MEMORY_BASIC_INFORMATION 结构。所以_address应该是一个PVOID,可以通过简单的赋值来复制。
猜你喜欢
  • 2012-11-26
  • 1970-01-01
  • 2014-10-26
  • 1970-01-01
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 2017-03-15
相关资源
最近更新 更多