Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Непонятная ошибка при работе со строками


Автор: uwannadie 23.5.2011, 10:49
отлаживал программу ,пытаяся выловить AV. для этого подключил FASTMM
после подключения имеем налицо ошибку в строчке
Код

aSourcePath := pSourcePath + '\' + pFilePath;

лог фастмм-а:
Код

--------------------------------2011/5/23 10:32:41--------------------------------
FastMM has detected an error during a GetMem operation. The block header has been corrupted. 

The current thread ID is 0xBCC, and the stack trace (return addresses) leading to this error is:
40E94D [FastMM4.pas][FastMM4][FastMM4.DebugGetMem][6843]
4EBCEE [BuildThread.pas][BuildThread][BuildThread.TBuildThread.Execute][164]
44CFD1 [Classes.pas][Classes][Classes.ThreadProc][11407]
7C80B729 [Unknown function at GetModuleFileNameA]

сама ошибка возникает в System._NewUnicodeString:
Код

function _NewUnicodeString(CharLength: LongInt): Pointer;
{$IFDEF PUREPASCAL}
var
  P: PStrRec;
begin
  Result := nil;
  if CharLength > 0 then
  begin
    // Allocate a memory with record and extra wide-null terminator.
    if CharLength >= (MaxInt - SizeOf(StrRec)) div SizeOf(WideChar) then _IntOver;
    GetMem(P, SizeOf(StrRec) + (CharLength + 1) * SizeOf(WideChar));
    Result := Pointer(NativeInt(P) + SizeOf(StrRec));
    P.length := CharLength;
    P.refCnt := 1;
    P.elemSize := SizeOf(WideChar);
    P.codePage := Word(DefaultUnicodeCodePage);
    PWideChar(Result)[CharLength] := #0;
  end;
end;
{$ELSE}
asm
        { ->    EAX     length                  }
        { <-    EAX     pointer to new string   }
        TEST    EAX,EAX
        JLE     @@lengthLEZero  // length <= 0?
        PUSH    EAX             // save length
        ADD     EAX,EAX         // convert to bytes
        JO      @@overflow
        ADD     EAX,rOff+2      // + record + terminator
        JO      @@overflow
        {$IFDEF ALIGN_STACK}
        SUB     ESP,8
        {$ENDIF ALIGN_STACK}
        CALL    _GetMem                       //<<<<< ======= тут возникает ошибка
        {$IFDEF ALIGN_STACK}
        ADD     ESP,8
        {$ENDIF ALIGN_STACK}
        ADD     EAX,rOff
        POP     EDX                              // requested string length
        MOV     [EAX-skew].StrRec.refCnt,1
        MOV     [EAX-skew].StrRec.length,EDX
        MOV     word ptr [EAX+EDX*2],0           // wide null terminator
        MOV     word ptr [EAX-skew].StrRec.elemSize,2
{$IFDEF PIC}
        PUSH    EBX
        PUSH    EAX
        PUSH    ECX
        CALL    GetGOT
        MOV     EDX, [EAX].OFFSET DefaultUnicodeCodePage
        MOV     EDX, [EDX]
        POP     ECX
        POP     EAX
        POP     EBX
{$ELSE !PIC}
        MOV     EDX, DefaultUnicodeCodePage
{$ENDIF}
        MOV     word ptr [EAX-skew].StrRec.codePage,DX
        RET
@@overflow:
        {$IFDEF ALIGN_STACK}
        POP     EAX
        {$ENDIF ALIGN_STACK}
        JMP     _IntOver
@@lengthLEZero:
        XOR     EAX,EAX
end;
{$ENDIF !PUREPASCAL}

на борту 
Embarcadero® Delphi® XE Version 15.0.3953.35171 
FastMM 4.97
на всякий пожарный прилагаю код модуля, в котором находится строка с ошибкой

Добавлено через 5 минут и 14 секунд
UPD
выключил FastMM, ошибка исчезла, но появляется старый AV :(

Автор: MetalFan 23.5.2011, 14:19
uwannadie, сразу бросилась в глаза неинициализированная локальная переменная в цикле
Код

    for i := 0 to pFilePriority.Count - 1 do
      Tmp := Tmp + pFilePriority.Strings[i]+';';

Ну и по StrLCopy замечание... учитывается ли, что Dest должно быть размером MaxLen+1 для null terminator'а?
Может еще какие косяки есть.

Автор: uwannadie 23.5.2011, 15:12
Цитата(MetalFan @  23.5.2011,  14:19 Найти цитируемый пост)
Ну и по StrLCopy замечание... учитывается ли, что Dest должно быть размером MaxLen+1 для null terminator'а?
Может еще какие косяки есть. 

- в смысле поставить в параметр MaxLen в моем случае размер массива + 1 ?
- ну очевидные косяки исправил. типа соответствия типов и освобождения объектов и удаление указателей на них

самое интересное, что на системах с полноценной поддержкой AV не появляется (проверял на висте, семерке)
может где-то тут собака зарыта?

Автор: northener 23.5.2011, 15:24
Цитата(uwannadie @  23.5.2011,  15:12 Найти цитируемый пост)
самое интересное, что на системах с полноценной поддержкой AV не появляется (проверял на висте, семерке)
может где-то тут собака зарыта?

Появление или не появление AV это дело случая. Появление AV есть прямое указание на ошибку в программе, отсутствие AV ни о чем не говорит.

Автор: uwannadie 23.5.2011, 15:29
ну это ясно.
в общем ошибка со строкой исчезла совсем после правки параметров StrLCopy
теперь FASTMM добрался до основного гвоздя - AV  smile 

Автор: MetalFan 23.5.2011, 17:27
Цитата(uwannadie @  23.5.2011,  15:12 Найти цитируемый пост)
- в смысле поставить в параметр MaxLen в моем случае размер массива + 1 ?

Всмысле, что размер Dest = MaxLen+1, т.е. эта функция запишет MaxLen cимволов, и в конце добьет нулем. В твоем случае, если строка слишком длинная, то ноль этот улетал за пределы Dest.

Автор: uwannadie 23.5.2011, 17:59
Цитата(MetalFan @ 23.5.2011,  17:27)
Цитата(uwannadie @  23.5.2011,  15:12 Найти цитируемый пост)
- в смысле поставить в параметр MaxLen в моем случае размер массива + 1 ?

Всмысле, что размер Dest = MaxLen+1, т.е. эта функция запишет MaxLen cимволов, и в конце добьет нулем. В твоем случае, если строка слишком длинная, то ноль этот улетал за пределы Dest.

ну это понятно, но я думаю тут проблема решилась бы проверкой длины массива символов вида
Код

длина массива <= MAX_PATH - 1

как раз 1 место для #0 останется в любом случае

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)