Seite 1 von 1

große Strings

Verfasst: 21.09.2005 21:22
von Deeem2031
Wer unbedingt große Strings haben will, die erst dann allociert werden wenn sie gebraucht werden, der kann jetzt diese Procs nehmen und sich freuen :wink:
Vorteil gegenüber SetStringBufferSize() ist, wie schon gesagt, dass die Größe des StringBuffers nicht festgesetzt wird und der Buffer erst vergrößert wird, wenns auch nötig ist. Aber seht selbst:

...ist übrigens in Zusammenarbeit mit Purefan entstanden :)

Code: Alles auswählen

Structure EXCEPTIONREPORTRECORD
  ExceptionCode.l
  fHandlerFlags.l
  *NestedExceptionReportRecord.EXCEPTIONREPORTRECORD
  *ExceptionAddress.l
  cParameters.l
  ExceptionInfo.l[#EXCEPTION_MAXIMUM_PARAMETERS]
EndStructure

;{ BigString
Global BigString_Base, BigString_BaseSize, BigString_OldExceptionHandler

DisableDebugger
Procedure StringExceptionHandler(*ExceptionInfo.EXCEPTION_POINTERS)
  Protected BigString_BaseEnd, tmp
  *ExceptionRecord.EXCEPTIONREPORTRECORD = *ExceptionInfo\pExceptionRecord
  If *ExceptionRecord\ExceptionCode = #EXCEPTION_ACCESS_VIOLATION
    If *ExceptionRecord\cParameters = 2
      BigString_BaseEnd = BigString_Base+BigString_BaseSize
      If *ExceptionRecord\ExceptionInfo[1]&$FFFFF000 = BigString_BaseEnd-$1000 
        VirtualProtect_(BigString_BaseEnd-$1000,$1000,#PAGE_READWRITE,@tmp)
        If VirtualAlloc_(BigString_BaseEnd,$1000,#MEM_COMMIT,#PAGE_NOACCESS)
          BigString_BaseSize+$1000
          ProcedureReturn #EXCEPTION_CONTINUE_EXECUTION
        EndIf
        MessageRequester("Error","Kein Speicher mehr da, der String ist zu groß.",16)
      EndIf
    EndIf
  EndIf
  ProcedureReturn CallFunctionFast(BigString_OldExceptionHandler,*ExceptionInfo)
EndProcedure
EnableDebugger

Procedure InitBigString()
  If BigString_Base
    VirtualFree_(BigString_Base, BigString_BaseSize, #MEM_RELEASE)
  EndIf
  
  BigString_Base = VirtualAlloc_(#Null,$10000000,#MEM_RESERVE,#PAGE_READWRITE)
  If BigString_Base
    BigString_BaseSize = $2000
    !PUSH dword[PB_StringBase]
    !PUSH 0
    !PUSH dword[PB_MemoryBase]
    !EXTRN _HeapFree@12
    !CALL _HeapFree@12
    If VirtualAlloc_(BigString_Base,BigString_BaseSize,#MEM_COMMIT,#PAGE_READWRITE)
      !MOV dword[PB_StringBase], Eax
      VirtualProtect_(BigString_Base+(BigString_BaseSize-$1000),$1000,#PAGE_NOACCESS,@tmp)
      BigString_OldExceptionHandler = SetUnhandledExceptionFilter_(@StringExceptionHandler())
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure FreeBigString()
  VirtualFree_(BigString_Base, BigString_BaseSize, #MEM_RELEASE)
  SetUnhandledExceptionFilter_(BigString_OldExceptionHandler)
  !PUSH 64000
  !PUSH 8 ;HEAP_ZERO_MEMORY
  !PUSH dword[PB_MemoryBase]
  !EXTRN _HeapAlloc@12
  !CALL _HeapAlloc@12
  !MOV dword[PB_StringBase], Eax 
EndProcedure

;}

If InitBigString()
  
  For i2 = 1 To 10
    x.s = ""
    For i = 1 To i2
      x + Space(65536)
    Next
    MessageRequester("",Str(i2)+"*64KB = "+Str(Len(x)))
  Next
  
  FreeBigString()
Else
  MessageRequester("","Alloc-Prob",16)
EndIf

Verfasst: 21.09.2005 21:30
von ts-soft
:allright: , sehr nützlich

Verfasst: 21.09.2005 21:57
von Deeem2031
Ich hab 2 Dinge vergessen:
1. Kein Debug damit benutzen, der StringBuffer vom Debugger wird damit nicht beeinflusst, er unterstützt also weiterhin nur 64000 byte. (Ist aber bei SetStringBufferSize() auch so)
2. Wenn man das benutzt wird sogar in den meisten Fällen der Menge des Allocierten Speicherbereichs kleiner, weil am Anfang nur $1000 byte benutzt werden, nicht 64000. Wer darauf Wert legt, kann das also auch benutzen.

Nur einen Nachteil hat das Ganze, wird ein großer String geladen, kann es am Anfang ein bischen länger dauern, da er der Speiche allociert werden muss, normalerweise wird der ja gleich am Nafang von PB allociert. Ist der Speicher aber einmal geladen, ist es genauso schnell wie sonst auch.

Verfasst: 21.09.2005 22:20
von Kiffi
Danke! :allright:

Grüße ... Kiffi