<aw->
tankf33der: how do you determine it's leaking?
<tankf33der>
You should run two files exactly as paste shows
<tankf33der>
Load the file in the loop,
<tankf33der>
If run malloc without load it does not leak
<abu[7]>
ok
<aw->
yeah, so each (load) creates a new symbol?
<abu[7]>
right, size increases
<abu[7]>
A 'load' without malloc/free does net increase
<abu[7]>
strange!
<abu[7]>
The 'let' can be omitted:
<abu[7]>
(%@ "free" NIL (%@ "malloc" 'P 224))
<tankf33der>
right
<tankf33der>
afk
rob_w has quit [Remote host closed the connection]
<abu[7]>
Interesting, the 'malloc'ed size does not matter. So free() itself works.
<tankf33der>
Without free it would increase faster, much faster
<abu[7]>
right
<tankf33der>
try (buf …
<tankf33der>
and try (%@ “strdup” …
<abu[7]>
buf does not malloc anything
<abu[7]>
it reserves stack space
<tankf33der>
ok
<abu[7]>
It is also not open+close of files, because if instead of (do 99999 (load "mem.l")) I do (do 99999 (in "mem.l" (eval (read)))) it does *not* increase
<abu[7]>
<abu[7]>
"mem.l" is a single line (%@ "free" NIL (%@ "malloc" 'P 99))
<abu[7]>
This makes absolutely no sense to me
<abu[7]>
How can we find out *which* part of the memory gets bigger?
<abu[7]>
Ha! It is free() alone too!
<abu[7]>
Just (%@ "free" NIL 0) already increases
<abu[7]>
but it increases not so much as with malloc
<abu[7]>
Is it the native call?
<abu[7]>
yes
<abu[7]>
(%@ "getenv" 'S "TERM") also increases
<abu[7]>
any native call
<abu[7]>
e.g. (%@ "addu" T '(T . 3) '(T . 4)) -> 7
<abu[7]>
Oh, I think I know
<abu[7]>
It must be the library which gets opened repeatedly
<abu[7]>
Yes! It is the lib!
<abu[7]>
Change the file to (native *Lib "getenv" 'S "TERM")
<abu[7]>
and then
<abu[7]>
: (setq *Lib "@")
<abu[7]>
(do 99999 (load "mem.l"))
<abu[7]>
No more increase!
<abu[7]>
(native *Lib ... re-uses the same transient symbol "@" (which holds the library handle after the first call)
<abu[7]>
If "@" is used *inside* the file, it is a new transient symbol each time, and so the library gets loaded into memory each time
<abu[7]>
'load' keeps transient symbols private
<abu[7]>
But I don't understand why this is also for '%@' ...
beneroth has quit [Ping timeout: 240 seconds]
beneroth has joined #picolisp
<beneroth>
but if its transient symbols, so additional pil-managed-memory usage... then a (gc) should clean it, no?
<abu[7]>
No, this is not the probleon
<abu[7]>
problem
<abu[7]>
Not Lisp heap
<abu[7]>
The library get loaded each time
<abu[7]>
But there is still something I don't understand
<beneroth>
ah.. kinda loading the shared library for each call into memory
<abu[7]>
Investigating ...
<abu[7]>
yes
<abu[7]>
bbl
<beneroth>
see ya :)
<abu[7]>
I'm outside in the rain ;)
<abu[7]>
Can't type on a wet Penti
<tankf33der>
:)
<abu[7]>
Anyway I'm wrong. (%@ "getenv" 'S "TERM") does not specify the lib as a transient, and there is even no lib loading involved because it uses the binary itself, which is already loaded.
<abu[7]>
Must think more (still walking)
<abu[7]>
Now I found the true reason
<abu[7]>
It is not the library, but the ffi structure allocated in the value of the transient symbol
<tankf33der>
Eh
<abu[7]>
In (%@ "getenv" 'S "TERM") it is "getenv"
<abu[7]>
It holds a pointer to the prepared C call
<abu[7]>
Prepare is quite expensive, so the pointer is cached
<beneroth>
so (native) itself is causing the leaking, though it might be different depending on what gets allocated?
<beneroth>
bbl
<abu[7]>
The alloced size is always the same, one per function
<abu[7]>
ffi *ffiPrep(char *lib, char *fun, ... in @src/lib.c
<abu[7]>
OK, the size differs for each function, depending on its arguments
<abu[7]>
This is done once for each function
<abu[7]>
eg. "getenv"
<abu[7]>
Then the symbol "getenv" stores this pointer in its value, and native directly uses it on all following calls
<abu[7]>
But in 'load' transients are locally scoped
<abu[7]>
so we get a new one each time
<abu[7]>
The scoping is needed here for native calls
<abu[7]>
becaus "getenv" might also be in another library and gets a different structure
<abu[7]>
So there is not really a solution
pablo_escoberg has joined #picolisp
<abu[7]>
Whe idea with native calls was that they reside in lib files which are loaded just once and then called
<tankf33der>
this is ok. as is.
<abu[7]>
One could free it manually, but that's ugly
<abu[7]>
Should be a warning in the docs
pablo_escoberg has quit [Quit: Client closed]
pablo_escoberg has joined #picolisp
<pablo_escoberg>
I'm having a rather funny time trying to figure out how to get a transient symbol containing a single backslash followed by a single quote. which is to say, I need a function that returns "\'" (I'm doing sql sanitization). It's really the single backslash that's giving me agida. How do you do this in picolisp?
<abu[7]>
"\\'"
<abu[7]>
Like in most languages like C
<abu[7]>
The backslash is a markup (also the double quote) in a string, so it must itself be escaped
<abu[7]>
The caret ^ is also a markup
<abu[7]>
for Control chars
<abu[7]>
I think this is all described in @doc/ref.html
<pablo_escoberg>
ah, ok. I was confused by the way it was displaying. My initial instinct on how to do this was correct, but I kept seeing what looked wrong. TY.
<abu[7]>
Yeah, read and print are symmetrical in PicoLisp
<abu[7]>
"\\" is a single char, and it prigts as "\\"
<abu[7]>
: (char 92) -> "\\"
seninha has joined #picolisp
<pablo_escoberg>
oh, ok, that explains it better as well.
pablo_escoberg has quit [Quit: Client closed]
msavoritias has quit [Remote host closed the connection]