Skip to content

Commit 2f9bda0

Browse files
authored
Merge pull request #248 from boriel/bugfix/letarraysubstr_memleak
Bugfix/letarraysubstr memleak
2 parents 4ace5f0 + c5c3155 commit 2f9bda0

18 files changed

Lines changed: 3703 additions & 1294 deletions

arch/zx48k/translator.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,12 +336,12 @@ def visit_LETARRAYSUBSTR(self, node):
336336

337337
expr = node.children[3] # right expression
338338
yield expr
339-
self.ic_param(TYPE.string, expr.t)
340339

341-
# TODO: this produces a memory leak
342-
if expr.token != 'STRING' and (expr.token != 'VAR' or expr.mangled[0] != '_'):
343-
self.ic_param(TYPE.ubyte, 1) # If the argument is not a variable, it must be freed
340+
if check.is_temporary_value(expr):
341+
self.ic_param(TYPE.string, expr.t)
342+
self.ic_param(TYPE.ubyte, 1)
344343
else:
344+
self.ic_param(gl.PTR_TYPE, expr.t)
345345
self.ic_param(TYPE.ubyte, 0)
346346

347347
yield node.children[1]

tests/functional/let_array_substr.asm

Lines changed: 81 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ __START_PROGRAM:
2020
ld de, __LABEL0
2121
call __STORE_STR
2222
ld hl, __LABEL1
23-
call __LOADSTR
2423
push hl
2524
xor a
2625
push af
@@ -200,7 +199,7 @@ __FNMUL2:
200199
TMP_ARR_PTR:
201200
DW 0 ; temporary storage for pointer to tables
202201
ENDP
203-
#line 61 "let_array_substr.bas"
202+
#line 60 "let_array_substr.bas"
204203
#line 1 "letsubstr.asm"
205204
; Substring assigment eg. LET a$(p0 TO p1) = "xxxx"
206205
; HL = Start of string
@@ -582,19 +581,30 @@ __FREE_STR:
582581
jp nz, __MEM_FREE
583582
ret
584583
ENDP
585-
#line 62 "let_array_substr.bas"
586-
#line 1 "loadstr.asm"
587-
#line 1 "alloc.asm"
584+
#line 61 "let_array_substr.bas"
585+
#line 1 "storestr.asm"
586+
; vim:ts=4:et:sw=4
587+
; Stores value of current string pointed by DE register into address pointed by HL
588+
; Returns DE = Address pointer (&a$)
589+
; Returns HL = HL (b$ => might be needed later to free it from the heap)
590+
;
591+
; e.g. => HL = _variableName (DIM _variableName$)
592+
; DE = Address into the HEAP
593+
;
594+
; This function will resize (REALLOC) the space pointed by HL
595+
; before copying the content of b$ into a$
596+
#line 1 "strcpy.asm"
597+
#line 1 "realloc.asm"
588598
; vim: ts=4:et:sw=4:
589599
; Copyleft (K) by Jose M. Rodriguez de la Rosa
590600
; (a.k.a. Boriel)
591601
; http://www.boriel.com
592602
;
593-
; This ASM library is licensed under the MIT license
603+
; This ASM library is licensed under the BSD license
594604
; you can use it for any purpose (even for commercial
595605
; closed source programs).
596606
;
597-
; Please read the MIT license on the internet
607+
; Please read the BSD license on the internet
598608
; ----- IMPLEMENTATION NOTES ------
599609
; The heap is implemented as a linked list of free blocks.
600610
; Each free block contains this info:
@@ -635,7 +645,7 @@ __FREE_STR:
635645
; | (0 if Size = 4)|
636646
; +----------------+
637647
; When a block is FREED, the previous and next pointers are examined to see
638-
; if we can defragment the heap. If the block to be freed is just next to the
648+
; if we can defragment the heap. If the block to be breed is just next to the
639649
; previous, or to the next (or both) they will be converted into a single
640650
; block (so defragmented).
641651
; MEMORY MANAGER
@@ -676,7 +686,67 @@ __ERROR_CODE:
676686
__STOP:
677687
ld (ERR_NR), a
678688
ret
679-
#line 69 "alloc.asm"
689+
#line 70 "realloc.asm"
690+
#line 1 "alloc.asm"
691+
; vim: ts=4:et:sw=4:
692+
; Copyleft (K) by Jose M. Rodriguez de la Rosa
693+
; (a.k.a. Boriel)
694+
; http://www.boriel.com
695+
;
696+
; This ASM library is licensed under the MIT license
697+
; you can use it for any purpose (even for commercial
698+
; closed source programs).
699+
;
700+
; Please read the MIT license on the internet
701+
; ----- IMPLEMENTATION NOTES ------
702+
; The heap is implemented as a linked list of free blocks.
703+
; Each free block contains this info:
704+
;
705+
; +----------------+ <-- HEAP START
706+
; | Size (2 bytes) |
707+
; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK
708+
; +----------------+
709+
; | Next (2 bytes) |---+
710+
; +----------------+ <-+
711+
; | Size (2 bytes) |
712+
; +----------------+
713+
; | Next (2 bytes) |---+
714+
; +----------------+ |
715+
; | <free bytes...>| | <-- If Size > 4, then this contains (size - 4) bytes
716+
; | (0 if Size = 4)| |
717+
; +----------------+ <-+
718+
; | Size (2 bytes) |
719+
; +----------------+
720+
; | Next (2 bytes) |---+
721+
; +----------------+ |
722+
; | <free bytes...>| |
723+
; | (0 if Size = 4)| |
724+
; +----------------+ |
725+
; <Allocated> | <-- This zone is in use (Already allocated)
726+
; +----------------+ <-+
727+
; | Size (2 bytes) |
728+
; +----------------+
729+
; | Next (2 bytes) |---+
730+
; +----------------+ |
731+
; | <free bytes...>| |
732+
; | (0 if Size = 4)| |
733+
; +----------------+ <-+
734+
; | Next (2 bytes) |--> NULL => END OF LIST
735+
; | 0 = NULL |
736+
; +----------------+
737+
; | <free bytes...>|
738+
; | (0 if Size = 4)|
739+
; +----------------+
740+
; When a block is FREED, the previous and next pointers are examined to see
741+
; if we can defragment the heap. If the block to be freed is just next to the
742+
; previous, or to the next (or both) they will be converted into a single
743+
; block (so defragmented).
744+
; MEMORY MANAGER
745+
;
746+
; This library must be initialized calling __MEM_INIT with
747+
; HL = BLOCK Start & DE = Length.
748+
; An init directive is useful for initialization routines.
749+
; They will be added automatically if needed.
680750
; ---------------------------------------------------------------------
681751
; MEM_ALLOC
682752
; Allocates a block of memory in the heap.
@@ -772,114 +842,7 @@ __MEM_SUBTRACT:
772842
inc hl ; Return hl
773843
ret
774844
ENDP
775-
#line 2 "loadstr.asm"
776-
; Loads a string (ptr) from HL
777-
; and duplicates it on dynamic memory again
778-
; Finally, it returns result pointer in HL
779-
__ILOADSTR: ; This is the indirect pointer entry HL = (HL)
780-
ld a, h
781-
or l
782-
ret z
783-
ld a, (hl)
784-
inc hl
785-
ld h, (hl)
786-
ld l, a
787-
__LOADSTR: ; __FASTCALL__ entry
788-
ld a, h
789-
or l
790-
ret z ; Return if NULL
791-
ld c, (hl)
792-
inc hl
793-
ld b, (hl)
794-
dec hl ; BC = LEN(a$)
795-
inc bc
796-
inc bc ; BC = LEN(a$) + 2 (two bytes for length)
797-
push hl
798-
push bc
799-
call __MEM_ALLOC
800-
pop bc ; Recover length
801-
pop de ; Recover origin
802-
ld a, h
803-
or l
804-
ret z ; Return if NULL (No memory)
805-
ex de, hl ; ldir takes HL as source, DE as destiny, so SWAP HL,DE
806-
push de ; Saves destiny start
807-
ldir ; Copies string (length number included)
808-
pop hl ; Recovers destiny in hl as result
809-
ret
810-
#line 63 "let_array_substr.bas"
811-
#line 1 "storestr.asm"
812-
; vim:ts=4:et:sw=4
813-
; Stores value of current string pointed by DE register into address pointed by HL
814-
; Returns DE = Address pointer (&a$)
815-
; Returns HL = HL (b$ => might be needed later to free it from the heap)
816-
;
817-
; e.g. => HL = _variableName (DIM _variableName$)
818-
; DE = Address into the HEAP
819-
;
820-
; This function will resize (REALLOC) the space pointed by HL
821-
; before copying the content of b$ into a$
822-
#line 1 "strcpy.asm"
823-
#line 1 "realloc.asm"
824-
; vim: ts=4:et:sw=4:
825-
; Copyleft (K) by Jose M. Rodriguez de la Rosa
826-
; (a.k.a. Boriel)
827-
; http://www.boriel.com
828-
;
829-
; This ASM library is licensed under the BSD license
830-
; you can use it for any purpose (even for commercial
831-
; closed source programs).
832-
;
833-
; Please read the BSD license on the internet
834-
; ----- IMPLEMENTATION NOTES ------
835-
; The heap is implemented as a linked list of free blocks.
836-
; Each free block contains this info:
837-
;
838-
; +----------------+ <-- HEAP START
839-
; | Size (2 bytes) |
840-
; | 0 | <-- Size = 0 => DUMMY HEADER BLOCK
841-
; +----------------+
842-
; | Next (2 bytes) |---+
843-
; +----------------+ <-+
844-
; | Size (2 bytes) |
845-
; +----------------+
846-
; | Next (2 bytes) |---+
847-
; +----------------+ |
848-
; | <free bytes...>| | <-- If Size > 4, then this contains (size - 4) bytes
849-
; | (0 if Size = 4)| |
850-
; +----------------+ <-+
851-
; | Size (2 bytes) |
852-
; +----------------+
853-
; | Next (2 bytes) |---+
854-
; +----------------+ |
855-
; | <free bytes...>| |
856-
; | (0 if Size = 4)| |
857-
; +----------------+ |
858-
; <Allocated> | <-- This zone is in use (Already allocated)
859-
; +----------------+ <-+
860-
; | Size (2 bytes) |
861-
; +----------------+
862-
; | Next (2 bytes) |---+
863-
; +----------------+ |
864-
; | <free bytes...>| |
865-
; | (0 if Size = 4)| |
866-
; +----------------+ <-+
867-
; | Next (2 bytes) |--> NULL => END OF LIST
868-
; | 0 = NULL |
869-
; +----------------+
870-
; | <free bytes...>|
871-
; | (0 if Size = 4)|
872-
; +----------------+
873-
; When a block is FREED, the previous and next pointers are examined to see
874-
; if we can defragment the heap. If the block to be breed is just next to the
875-
; previous, or to the next (or both) they will be converted into a single
876-
; block (so defragmented).
877-
; MEMORY MANAGER
878-
;
879-
; This library must be initialized calling __MEM_INIT with
880-
; HL = BLOCK Start & DE = Length.
881-
; An init directive is useful for initialization routines.
882-
; They will be added automatically if needed.
845+
#line 71 "realloc.asm"
883846
; ---------------------------------------------------------------------
884847
; MEM_REALLOC
885848
; Reallocates a block of memory in the heap.
@@ -1050,7 +1013,7 @@ __STORE_STR:
10501013
ld (hl), d ; Stores a$ ptr into elemem ptr
10511014
pop hl ; Returns ptr to b$ in HL (Caller might needed to free it from memory)
10521015
ret
1053-
#line 64 "let_array_substr.bas"
1016+
#line 62 "let_array_substr.bas"
10541017
ZXBASIC_USER_DATA:
10551018
_b:
10561019
DEFB 03h

0 commit comments

Comments
 (0)