Hey, wanted to ask this:
proc ff(j:int) : void =
var dd {.noinit.}: int
dd.echo
2.ff
Now dd is 0. But shouldnt it be an arbitrary value like 1710401292?
Thanks?
EDIT: Had to clarify the code ;)
Yes, and for me it is:
$ nim c -r t.nim
Hint: used config file '/home/stefan/Nim/config/nim.cfg' [Conf]
Hint: system [Processing]
Hint: t [Processing]
CC: t
CC: stdlib_system
Hint: [Link]
Hint: operation successful (11719 lines compiled; 0.667 sec total; 22.539MiB peakmem; Debug Build) [SuccessX]
Hint: /tmp/hhh/t [Exec]
94177739211386
stefan@nuc /tmp/hhh $ ./t
94314291364474
stefan@nuc /tmp/hhh $ ./t
94655466492538
stefan@nuc /tmp/hhh $ nim -v
Nim Compiler Version 0.18.0 [Linux: amd64]
Copyright (c) 2006-2018 by Andreas Rumpf
git hash: 4164ec4f8b6d9968e69381edd35d9cf6fe79dee1
active boot switches: -d:release
You may inspect the C code to see that var is not initialized. dd var is located on the stack and may be zero if never another value was written to this location. You may try to call another proc which writes some values to local variables, that should pollute the stack. And then call your ff proc.
@Stefan_Salewski
Thank you!
You may try to call another proc which writes some values to local variables, that should pollute the stack. And then call your ff proc.
That tip was priceless!
This works:
from random import rand
proc ff(_: int) =
var
iNoInit {.noinit.}: int
iAutoInit: int
echo "auto-init int var=", iAutoInit, ", noinit int var=", iNoInit
for i in 0..1000:
ff(rand(i))
OK, I cannot seem to edit my last post. I forgot to post the output. So here it is:
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
auto-init int var=0, noinit int var=65536
Interestingly, the noinit var iNoInit, though not the auto-init value 0, always has the same value. How can I force flush the stack or overwrite it with something else? I am calling rand with a different value each time, but that doesn't seem to work.
No, you got me wrong. I am trying "some way" to pollute the stack to see that a var with {.noinit.} shows some random value other than the auto-init value of 0.
I just want to verify that {.noinit.} works.
This is in reference to https://github.com/nim-lang/Nim/issues/7852#issuecomment-390715981.
Nim lacks a function to introspect if a variable is actually uninitialized. So I am going through such hoops to better understand things.
Hello @jxy,
I have this example Nim snippet:
var a_global: int
proc foo() =
var
a_local_auto_init: int
a_local_noinit {.noInit.}: int
echo "Value of auto-initialized local variable 'a_local_auto_init': ", a_local_auto_init
echo "Value of uninitialized local variable 'a_local_noinit': ", a_local_noinit
echo "Value of auto-initialized global variable 'a_global': ", a_global
foo()
That generated this: https://gist.github.com/d874d983801caf1c2b6c1fae0bcee109
I think I understand where the local var a_local_auto_init get auto-initialized.. this part?
N_LIB_PRIVATE N_NIMCALL(void, foo_Ye5ZMhVNobnVQY9aJAVUuyQ)(void) {
NI a_local_auto_init;
NI a_local_noinit;
tyArray_Re75IspeoxXy2oCZHwcRrA T1_;
tyArray_Re75IspeoxXy2oCZHwcRrA T2_;
a_local_auto_init = (NI)0;
memset((void*)T1_, 0, sizeof(tyArray_Re75IspeoxXy2oCZHwcRrA));
T1_[0] = copyString(((NimStringDesc*) &TM_5p9cPJYy9aij133bkKgd2i7g_3));
T1_[1] = nimIntToStr(a_local_auto_init);
echoBinSafe(T1_, 2);
memset((void*)T2_, 0, sizeof(tyArray_Re75IspeoxXy2oCZHwcRrA));
T2_[0] = copyString(((NimStringDesc*) &TM_5p9cPJYy9aij133bkKgd2i7g_4));
T2_[1] = nimIntToStr(a_local_noinit);
echoBinSafe(T2_, 2);
}
a_local_auto_init = (NI)0;
_I don't understand what NI is though.._
The global variable a_global related code seems to be this:
N_LIB_PRIVATE N_NIMCALL(void, NimMainModule)(void) {
tyArray_Re75IspeoxXy2oCZHwcRrA T1_;
memset((void*)T1_, 0, sizeof(tyArray_Re75IspeoxXy2oCZHwcRrA));
T1_[0] = copyString(((NimStringDesc*) &TM_5p9cPJYy9aij133bkKgd2i7g_2));
T1_[1] = nimIntToStr(a_global_nKNA5KkJyG5TaA0geqN0RQ);
echoBinSafe(T1_, 2);
foo_Ye5ZMhVNobnVQY9aJAVUuyQ();
}
But here, I don't see the assignment to (NI)0.. so how is that var auto-initialized?
Thanks.
_I don't understand what NI is though.._
NI is a type, meaning "Nim Int". Types like that are defined in lib/nimbase.h.
But here, I don't see the assignment to (NI)0.. so how is that var auto-initialized?
The a_global_nKNA5KkJyG5TaA0geqN0RQ variable is declared at line 45 in the generated code. It doesn't have an explicit initialization, but it's initialized by the C compiler anyway.
@GULPF I also first thought that that declaration on line 45 could have initialized the a_global (side question: How do you mark up monospace as you would do using backticks in markdown?).
But then I also see the same NI declarations for both a_local_noinit and a_local_auto_init too:
NI a_local_auto_init;
NI a_local_noinit;
So I put that thought away.
it's initialized by the C compiler anyway.
Or the OS.
(side question: How do you mark up monospace as you would do using backticks in markdown?)
RST uses double backticks for monospace. You can click on the "Styling with RST is supported" link when writing a post to see what's supported: https://forum.nim-lang.org/about/rst.
Thanks. I regretted typing that as I noticed that "Styling with RST.." link shortly after that.. not sure why I didn't see it before.
But coming back to the NI declarations.. all 3 variables (a_global, a_local_noinit, a_local_auto_inst) have that declaration. Does the NI declaration behave differently when called inside the N_LIB_PRIVATE N_NIMCALL vs out in the global scope area?
But coming back to the NI declarations.. all 3 variables (a_global, a_local_noinit, a_local_auto_inst) have that declaration. Does the NI declaration behave differently when called inside the N_LIB_PRIVATE N_NIMCALL vs out in the global scope area?
The initialization doesn't have anything to do with the declaration, sorry if confused you. Local C variables requires explicit initialization like the one on line 55, otherwise they might contain garbage. Global C variables, however, are initialized even they don't have any explicit initialization.