memcpy() случайно вылетает

Я использую 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.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


person Community    schedule 15.10.2009    source источник
comment
Я думаю, нам нужно увидеть код   -  person mmmmmm    schedule 15.10.2009
comment
ошибка не в memcpy, нам нужно увидеть ваш код, возможно, неверный указатель или переполнение буфера в стеке или другой памяти.   -  person kenny    schedule 15.10.2009


Ответы (7)


Есть два весьма вероятных объяснения:

  1. Вы используете memcpy для перекрывающихся адресов — поведение в этой ситуации не определено. Если вам требуется возможность обработки перекрывающихся адресов, std::memmove является " эквивалентный" инструмент.
  2. Вы используете memcpy для копирования в/из памяти, недоступной для вашей программы.

Из кода, который вы показали, похоже, что (2) является более вероятным сценарием. Поскольку вы можете отлаживать исходный код, попробуйте установить точку останова до того, как произойдет memcpy, и убедитесь, что все аргументы memcpy совпадают (т. е. source + num < dest или source > dest + num).

person Mark Rushakoff    schedule 15.10.2009

Из дизассемблированного кода видно, что указатель источника находится не в вашем адресном пространстве. rep movsb копирует из ds:si в es:di. ?? указывает, что память в ds:si не может быть прочитана.

person Community    schedule 15.10.2009

Похоже, вы перешли конец буфера и сгенерировали нарушение прав доступа.

Изменить: по-прежнему недостаточно информации. Мы не можем обнаружить ошибку, не зная гораздо больше о том, как выделяется буфер, в который вы пытаетесь скопировать, достаточно ли в нем места (я подозреваю, что нет) и допустим ли размер данных.

person Goz    schedule 15.10.2009

Если memcpy дает сбой, обычная причина в том, что вы передали недопустимые аргументы.

Обратите внимание, что при использовании memcpy источник и место назначения могут не пересекаться.

В таком случае используйте memmove.

person RED SOFT ADAIR    schedule 15.10.2009

из вашего кода "memcpy((char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize, data, dataSize)" и отладочной информации "данные" выглядят как локальная переменная ( в стеке), вы бы сделали «data = malloc(DATA_SIZE)» вместо «char data[DATA_SIZE]» и т. д.; в противном случае в вашей текущей строке кода «данные» уже были извлечены, что может привести к случайному сбою доступа к памяти.

person Community    schedule 15.10.2009

Всегда ли данные, на которые указывает (char *)dep + (int)sizeof(EntryRec) + (int)adp->fileHdr.keySize, имеют длину не менее dataSize?

Я сталкивался с подобными сбоями, когда строки переменной длины позже обрабатывались как фиксированные строки.

eg

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

Где fixedLength больше, чем 10. Очевидно, это были разные функции, поэтому проблема с длиной не была замечена. В большинстве случаев это будет работать, dest будет содержать «какую-то строку», а после нуля будет случайный мусор. В этом случае, если вы рассматриваете dest как строку с завершающим нулем, вы никогда этого не заметите, так как вы не увидите мусор после нуля.

Однако, если ptr выделено в конце страницы памяти, вы можете читать только до конца выделенной памяти и не дальше. Как только вы дочитаете до конца страницы, операционная система законно сломает вашу программу.

person Community    schedule 15.10.2009

Я бы предложил использовать memmove, так как он обрабатывает перекрывающиеся строки, при использовании memcpy в этой ситуации результат непредсказуем.

person Barry    schedule 15.10.2009