nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.46k stars 1.47k forks source link

Strange results when echoing the memory address of some pointers #1711

Closed jovial closed 8 years ago

jovial commented 9 years ago

Trying to print the memory address of some pointers yields strange results. Yet it is fine if I assign the result of the cast to a variable and then print the result.

type CArray*{.unchecked.}[T] = array[0..0, T]

proc main =
  var a = cast[CArray[ptr int]](alloc0(4 * sizeof(ptr int)))
  for i in 0..3:
    a[i] = cast[ptr int](alloc0(sizeof(int)))
    a[i][] = i

  let before = cast[int](a[2])
  echo cast[int](a[2])

  #let after = cast[int](a[2])
  echo cast[int](a[2])
  #assert before == after

main()

example output

140209307041920
0

Think this was leading to some other issues due to memory corruption.

jovial commented 9 years ago

Seems to be the cast to the CArray that causes this as it works if I cast to array[4,ptr int] instead. Is there a mistake in my code somewhere?

refi64 commented 9 years ago

For me, under the latest devel, this just crashes:

ryan@DevPC-LX:~/nim$ ./tst
139911396708480
139911396708480
Traceback (most recent call last)
tst.nim(16)              tst
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
ryan@DevPC-LX:~/nim$ 

But building with -d:release works:

ryan@DevPC-LX:~/nim$ ./tst
139818517663872
139818517663872
ryan@DevPC-LX:~/nim$ 

Here's the diff:

< static N_INLINE(NI, addInt)(NI a, NI b);
< N_NOINLINE(void, raiseOverflow)(void);
29,31d26
< static N_INLINE(void, nimFrame)(TFrame* s);
< N_NOINLINE(void, stackoverflow_18601)(void);
< static N_INLINE(void, popFrame)(void);
38,85d32
< extern TFrame* frameptr_16042;
< 
< static N_INLINE(NI, addInt)(NI a, NI b) {
<   NI result;
<   result = 0;
<   result = (NI)((NU64)(a) + (NU64)(b));
<   {
<       NIM_BOOL LOC3;
<       LOC3 = 0;
<       LOC3 = (0 <= (NI)(result ^ a));
<       if (LOC3) goto LA4;
<       LOC3 = (0 <= (NI)(result ^ b));
<       LA4: ;
<       if (!LOC3) goto LA5;
<       goto BeforeRet;
<   }
<   LA5: ;
<   raiseOverflow();
<   BeforeRet: ;
<   return result;
< }
< 
< static N_INLINE(void, nimFrame)(TFrame* s) {
<   NI LOC1;
<   LOC1 = 0;
<   {
<       if (!(frameptr_16042 == NIM_NIL)) goto LA4;
<       LOC1 = 0;
<   }
<   goto LA2;
<   LA4: ;
<   {
<       LOC1 = ((NI) ((NI16)((*frameptr_16042).calldepth + ((NI16) 1))));
<   }
<   LA2: ;
<   (*s).calldepth = ((NI16) (LOC1));
<   (*s).prev = frameptr_16042;
<   frameptr_16042 = s;
<   {
<       if (!((*s).calldepth == ((NI16) 2000))) goto LA9;
<       stackoverflow_18601();
<   }
<   LA9: ;
< }
< 
< static N_INLINE(void, popFrame)(void) {
<   frameptr_16042 = (*frameptr_16042).prev;
< }
93d39
<   nimfr("main", "tst.nim")
95,96d40
<   nimln(4, "tst.nim");
<   nimln(4, "tst.nim");
104d47
<       nimln(1576, "system.nim");
107d49
<           nimln(1577, "system.nim");
110d51
<               nimln(1577, "system.nim");
112d52
<               nimln(1576, "system.nim");
114,115d53
<               nimln(6, "tst.nim");
<               nimln(6, "tst.nim");
119d56
<               nimln(7, "tst.nim");
121,122c58
<               nimln(1579, "system.nim");
<               res_88052 = addInt(res_88052, 1);
---
>               res_88052 += 1;
126d61
<   nimln(9, "tst.nim");
128,129d62
<   nimln(10, "tst.nim");
<   nimln(10, "tst.nim");
133,134d65
<   nimln(13, "tst.nim");
<   nimln(13, "tst.nim");
138d68
<   popFrame();
181,182d110
<   nimfr("tst", "tst.nim")
<   nimln(16, "tst.nim");
184d111
<   popFrame();
jovial commented 9 years ago

I believe the mistake is in my code. I should have been casting to a ptr CArray:

type CArray*{.unchecked.}[T] = array[0..0, T]

proc main =
  let arrayAsPtr = alloc0(4 * sizeof(ptr int))
  var a = cast[ptr CArray[ptr int]](arrayAsPtr)
  for i in 0..3:
    a[i] = cast[ptr int](alloc0(sizeof(int)))
    a[i][] = i

  let before = cast[int](a[2])
  echo cast[int](a[2])

  #let after = cast[int](a[2])
  echo cast[int](a[2])
  #assert before == after

main()

see: http://forum.nimrod-lang.org/t/567#3035 for more details.

jangko commented 8 years ago

no longer a valid issue for nim 0.12.0

reactormonk commented 8 years ago

What would the expected output be?

jangko commented 8 years ago

@reactormonk: both of the echos output the same value

reactormonk commented 8 years ago

Works with -d:release, but not without. Close it?

jangko commented 8 years ago

need more investigation, my system: windows 7-32bit, minGW/GCC 4.8.1, both mode with/without -:release, don't have problem don't know about other system/platform, need more feedback from other users

dom96 commented 8 years ago

Works with both -d:release and without for me (Mac OS X/clang/Nim 0.12.1). Closing.