Either I'm confused or the gc is
schveiguy at gmail.com
Sun Nov 15 18:43:00 UTC 2020
On 11/15/20 10:05 AM, H. S. Teoh wrote:
> On Sun, Nov 15, 2020 at 01:43:14PM +0000, donallen via Digitalmars-d wrote:
>> With the help of an excellent suggestion by Steve Schveighoffer, I
>> finally identified this problem yesterday. It was my error, not D's.
>> void bind_text(sqlite3_stmt* stmt, int index, const char the_text)
>> if (sqlite3_bind_text(stmt, index, toStringz(the_text), -1, null)
>> != sqlite_ok)
>> stderr.writeln("bind_text failed");
>> auto db = sqlite3_db_handle(stmt);
>> stderr.writeln("Error: %s", fromStringz(sqlite3_errmsg(db)));
>> The culprit is the call to toStringz. The documentation for that
>> function give some good advice that I failed to follow:
>> "Important Note: When passing a char* to a C function, and the C
>> function keeps it around for any reason, make sure that you keep a
>> reference to it in your D code. Otherwise, it may become invalid
>> during a garbage collection cycle and cause a nasty bug when the C
>> code tries to use it."
> Ouch. I'm dismayed that I missed this when I last looked at this code
> (which I believe you did post here). ;-) Passing a GC-allocated string
> to C code without retaining a reference somewhere on the D side is a
> known gotcha when interfacing with C. In fact, I'm almost certain I ran
> into this very problem with toStringz myself in the past, yet I still
> failed to notice it when I looked at your code.
I had the same reaction! I also did not see the toStringz as a problem
when I reviewed.
I will note, also, that toStringz has this quirk where in certain cases
it just returns the pointer of the array, which is why I think the .idup
fix worked (that was puzzling to me and I think pulled me away from it
being a problem with storing a pointer in C-land only).
> In any case, I'm glad that this means you'll be around here more. ;-)
More information about the Digitalmars-d