große Strings

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

große Strings

Beitrag 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
Zuletzt geändert von Deeem2031 am 22.09.2005 20:42, insgesamt 1-mal geändert.
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

:allright: , sehr nützlich
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Deeem2031
Beiträge: 1232
Registriert: 29.08.2004 00:16
Wohnort: Vorm Computer
Kontaktdaten:

Beitrag 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.
Bild
[url=irc://irc.freenode.org/##purebasic.de]irc://irc.freenode.org/##purebasic.de[/url]
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

Danke! :allright:

Grüße ... Kiffi
a²+b²=mc²
Antworten