SQLite Forum

Possible misuse in pointer passing interface?
Login

Possible misuse in pointer passing interface?

(1) By Romain Doumenc (romaindoumenc) on 2022-10-07 09:19:22 [link] [source]

Hi,

I’d like to ask for a small clarification of the ownership of pointers in the pointer passing interface. Reading the documentation, it seems that §4 (stating that the ownership of the pointer remains on the application) contradicts slightly §3.2 (stating the ownership can be transferred to SQLite).

This has a consequence in a real use case: we created a virtual table to pass a complex data structure (lioli) to functions operating on pointers to this data structure (e.g. lioli_binary).

This is the plan we get when executing a select statement combining both:

sqlite> explain select lioli_binary(lioli) from origin limit 30;
addr  opcode         p1    p2    p3    p4             p5  comment      
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     15    0                    0   Start at 15
1     Integer        30    1     0                    0   r[1]=30; LIMIT counter
2     VOpen          0     0     0     vtab:603000000948  0   
3     Explain        3     0     0     SCAN origin VIRTUAL TABLE INDEX 1:I  0   
4     Integer        30    4     0                    0   r[4]=30
5     Integer        1     2     0                    0   r[2]=1
6     Integer        1     3     0                    0   r[3]=1
7     VFilter        0     14    2     I              0   iplan=r[2] zplan='I'
8       VColumn        0     2     6                    0   r[6]=vcolumn(2); fw_logs.lioli
9       Function       0     6     5     lioli_binary(1)  0   r[5]=func(r[6])
10      ReleaseReg     6     1     0                    0   release r[6] mask 0
11      ResultRow      5     1     0                    0   output=r[5]
12      DecrJumpZero   1     14    0                    0   if (--r[1])==0 goto 14
13    VNext          0     8     0                    0   
14    Halt           0     0     0                    0   
15    Transaction    0     0     1     0              1   usesStmtJournal=0
16    Goto           0     1     0                    0 

My understanding of this plan is that:

  • in step #8, the xColumn function is called to bind the result to the right column. We do so by calling
    sqlite3_result_pointer(ctx, (void *)c->lioli, "wt.software/lioli", release_record);
  • in step #9, the lioli_binary function is called
  • then, in step #10, the destructor release_record is called

But, using a simple print statement in both lioli_binary and release_record, we can show that the later is called before the former.

2022/10/07 09:59:57 destructor called
2022/10/07 09:59:57 lioli_binary called

Hence the question: where does the ownership reside in this case? When is it safe for the application to release values?

Thank you

(2) By Romain Doumenc (romaindoumenc) on 2022-10-07 09:35:49 in reply to 1 [source]

Sorry, bad logging got in the way: the destructor is indeed called after the call to the function.

So I assume the doc §3.2 is actually correct.