Remember all the fun we had last year when I failed to heed the warning in the toStringz documentation about retaining a reference to a char * passed into C? It took a long time to find that one, with a lot of help from Steve Schveighoffer and others.

Well, I've got another one. Consider this:

````
        // Get number of children of the parent account
auto gc_protect = bind_text(n_children_stmt, 1, parent.guid); parent.children.length = one_row!(int)(n_children_stmt, &get_int);

auto gc_protect2 = bind_text(account_child_stmt, 1, parent.guid); for (int i = 0; next_row_available_p(account_child_stmt, &sqlite3_reset); i++) {
            parent.children[i] = new Account;
parent.children[i].name = fromStringz(sqlite3_column_text(account_child_stmt, 0)).idup; parent.children[i].guid = fromStringz(sqlite3_column_text(account_child_stmt, 1)).idup; parent.children[i].flags = sqlite3_column_int(account_child_stmt, 2); parent.children[i].value = get_account_value(parent.children[i]);
        }
````
bind_text takes a D string, turns it into a C string with toStringz, uses that to call sqlite3_bind_text and returns the C string, which I store as you can see with the intention of protecting it from the gc. The code as written above does not work. At some point, I get an index-out-of-bounds error, because the loop is seeing too many children. If I turn off the GC, the code works correctly and the application completes normally.

With the GC on, if I put a debugging writeln inside the loop, right after the 'for', that prints, among other things, the value of gc_protect2 (I wanted to convince myself that the GC wasn't moving what it points to; yes, I know the documentation says the current GC won't do that), the problem goes away. A Heisenbug!

My theory: because gc_protect2 is never referenced, I'm guessing that the compiler is optimizing away the storage of the returned pointer, the supporting evidence being what I said in the previous paragraph. Anyone have a better idea?

By the way, I get the same error compiling this with dmd or ldc.

/Don Allen
  • More fun with toStringz an... Don Allen via Digitalmars-d-announce

Reply via email to