1

我在我的应用程序中使用 memcpy。memcpy 随机崩溃,下面是我在 Dr.Watson 文件中获得的日志。

        100181b5 8bd1             mov     edx,ecx
        100181b7 c1e902           shr     ecx,0x2
        100181ba 8d7c030c         lea     edi,[ebx+eax+0xc]
        100181be f3a5             rep     movsd
        100181c0 8bca             mov     ecx,edx
        100181c2 83e103           and     ecx,0x3
FAULT ->100181c5 f3a4             rep     movsb  ds:02a3b000=?? es:01b14e64=00
        100181c7 ff1508450210     call    dword ptr [Debug (10024508)]
        100181cd 83c424           add     esp,0x24
        100181d0 6854580210       push    0x10025854
        100181d5 ff1508450210     call    dword ptr [Debug (10024508)]
        100181db 83c404           add     esp,0x4

下面是代码

memcpy((char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize, data, dataSize ); 

在哪里:

  • dep 是一个结构
  • EntryRec 是一个字符指针
  • adp是一个结构
  • 数据不在NULL这种情况下

有没有人遇到过这个问题并且可以帮助我?

我试图调试 prog,然后我收到以下错误 Prog.exe(MSVCRTD.DLL) 中的未处理异常:0xC0000005: Access voilation

数据被传递给这个程序的参数,这是无效的*

更多信息:

我试图调试代码适配器在以下区域崩溃此函数存在于 OUTPUT.c 中(我认为这是一个库函数)

#else  /* _UNICODE */
            if (flags & (FL_LONG|FL_WIDECHAR)) {
                if (text.wz == NULL) /* NULL passed, use special string */
                    text.wz = __wnullstring;
                bufferiswide = 1;
                pwch = text.wz;
                while ( i-- && *pwch )
                    ++pwch;
                textlen = pwch - text.wz;
                /* textlen now contains length in wide chars */
            } else {
                if (text.sz == NULL) /* NULL passed, use special string */
                    text.sz = __nullstring;
                p = text.sz;
                while (i-- && *p) //Crash points here
                    ++p;
                textlen = p - text.sz;    /* length of the string */
            }

变量值:p=“”(未初始化)i=2147483598

4

7 回答 7

16

有两种很可能的解释:

  1. 您正在使用memcpy跨重叠地址——这种情况的行为是未定义的。如果您需要处理重叠地址的能力,std::memmove是“等效”工具。
  2. 您正在使用memcpy复制到/从您的程序无法访问的内存中。

从您显示的代码中,看起来 (2) 是更有可能的情况。由于您能够调试源代码,请尝试在memcpy发生之前设置断点,并验证memcpy所有参数是否匹配(即source + num < destsource > dest + num)。

于 2009-10-15T11:29:23.927 回答
10

从反汇编代码看来,源指针不在您的地址空间中。rep movsb 从 ds:si 复制到 es:di。这 ??表示无法读取 ds:si 处的内存。

于 2009-10-15T11:40:43.933 回答
1

如果 memcpy 崩溃,通常的原因是您传递了非法参数。

请注意,使用 memcpy 时,源和目标可能不会重叠。

在这种情况下,请使用 memmove。

于 2009-10-15T11:29:01.820 回答
1

指向的数据是否(char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize总是至少dataSize很长?

我遇到过类似的崩溃,其中可变长度字符串后来被视为固定字符串。

例如

char * ptr = strdup("some string");
// ...
memcpy(ptr, dest, fixedLength);

哪里fixedLength大于10。显然,它们具有不同的功能,因此没有注意到长度问题。大多数情况下,这将起作用,dest将包含“一些字符串”,并且在 null 之后将是随机垃圾。在这种情况下,如果您将 dest 视为以 null 结尾的字符串,您将永远不会注意到,因为您在 null 之后看不到垃圾。

但是,如果ptr在内存页的末尾分配,则只能读取到分配内存的末尾而不能进一步。一旦您阅读到页面末尾,操作系统就会正确地使您的程序崩溃。

于 2009-10-15T12:59:53.343 回答
1

从您的代码“memcpy((char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize, data, dataSize)”和调试信息来看,“数据”看起来像一个局部变量(堆栈变量),你会做“data = malloc(DATA_SIZE)”而不是“char data[DATA_SIZE]”等;否则,在您当前的代码行中,“数据”已经被弹出,因此可能会导致内存随机访问错误。

于 2009-10-15T11:59:54.240 回答
1

看起来您已经超出了缓冲区的末尾并产生了访问冲突。

编辑:仍然没有足够的信息。如果不知道更多关于您尝试复制到的缓冲区是否有足够的空间(我怀疑它没有)以及 dataSize 是否有效,我们就无法发现错误。

于 2009-10-15T11:27:19.593 回答
0

我建议使用 memmove 因为它处理重叠的字符串,在这种情况下使用 memcpy 时,结果是不可预测的。

于 2009-10-15T11:30:13.800 回答