I have the following example:
import math
{.emit: """
#include <stdio.h>
#include "e.h"
char *evil;
void weird_caller()
{
printf("Calling nimrod code, asking for cstring\n");
evil = gimme();
printf("Got '%s'\n", evil);
}
void second_guest()
{
printf("Displaying evil pointer %p\n", evil);
printf("Contents '%s'\n", evil);
}
""".}
proc gimme(): cstring {.exportc.} =
result = "Hey there C code! " & $random(100)
proc weird_caller() {.importc.}
proc second_guest() {.importc.}
proc tester() =
echo "Starting"
weird_caller()
echo "Doing second round"
second_guest()
when isMainModule:
tester()
tester()
which I compile and execute like:
$ nimrod c --header -r e.nim
Starting
Displaying evil pointer 0x0
Calling nimrod code, asking for cstring
Got 'Hey there C code! 7'
Doing second round
Displaying evil pointer 0x10c5d1060
Contents 'Hey there C code! 7'
Starting
Displaying evil pointer 0x10c5d1060
Calling nimrod code, asking for cstring
Got 'Hey there C code! 49'
Doing second round
Displaying evil pointer 0x10c5d1098
Contents 'Hey there C code! 49'
I wrote this exercise to look at the lifetime of the returned value. The generated code for the gimme proc is in C:
N_NIMCALL(NCSTRING, gimme)(void) {
NCSTRING result;
NimStringDesc* LOC1;
NI LOC2;
NimStringDesc* LOC3;
nimfr("gimme", "e.nim")
result = 0;
nimln(29, "e.nim");
nimln(29, "e.nim");
LOC1 = 0;
nimln(29, "e.nim");
nimln(29, "e.nim");
LOC2 = 0;
LOC2 = random_77549(100);
LOC3 = 0;
LOC3 = nimIntToStr(LOC2);
LOC1 = rawNewString(LOC3->Sup.len + 18);
appendString(LOC1, ((NimStringDesc*) &TMP128));
appendString(LOC1, LOC3);
result = LOC1->data;
popFrame();
return result;
}
From this it looks that the function is returning a pointer to the data of LOC1 (the string variable). But what's the lifetime of this variable? In this example everything works, but could the gc kick in and release LOC1 in popFrame? AFAICS nothing else points to or keeps LOC1 alive, so this behaviour is a bug and I should not rely on it?