Either I'm confused or the gc is

donallen donaldcallen at gmail.com
Wed Oct 21 16:24:41 UTC 2020


I'm new to D, but not to programming (I wrote my first line of 
code 60 years ago and am retired from a long career as a 
developer and project manager).

I have a suite of personal finance applications that I wrote in 
C. I'd like to port them to D. The financial data is stored in a 
sqlite database. I spent yesterday re-writing the verifier 
application in D and have run into a perplexing issue.

The verifier does a recursive descent of the tree of accounts, 
checking a bunch of things at each node. After the checks are 
done, a query is done to discover how many children the current 
account has, at which point it allocates, with 'new', a dynamic 
array of Account structs. It then goes into a loop, collecting 
information from the db about each of the children, which gets 
stored in one of the Account structs in the array. Finally, it 
does a
foreach through the array, doing a recursive call on the tree 
walker.

Here's the relevant code:
````
         // Now do the children of this account
         // First determine how many there are
         bind_text(count_children, 1, account.guid);
         int n_children = one_row(count_children, 
&get_int).integer_value;
         if (n_children > 0)
         {
             Account[] children = new Account[n_children];
             bind_text(find_children, 1, account.guid);
             int i = 0;
             while (next_row_available_p(find_children, 
&reset_stmt))
             {
                 if (i > n_children-1)
                     panic("walk_account_tree: child index exceeds 
n_children");
                 children[i].name = 
fromStringz(sqlite3_column_text(find_children, 0)).dup;
                 children[i].path = format("%s:%s", account.path, 
children[i].name);
                 children[i].guid = 
fromStringz(sqlite3_column_text(find_children, 1)).dup; // guid
                 children[i].commodity_guid = 
fromStringz(sqlite3_column_text(find_children, 2)).dup; // 
commodity_guid
                 children[i].flags = 
sqlite3_column_int(find_children,
                         3) | account.flags & 
(account_flag_descendents_are_assets
                         | 
account_flag_descendents_are_liabilities | 
account_flag_descendents_are_income
                         | account_flag_descendents_are_expenses | 
account_flag_descendents_are_marketable
                         | 
account_flag_self_and_descendents_are_tax_related
                         | 
account_flag_descendents_need_commodity_link); // flags
                 i = i + 1;
             }
             foreach (k, ref child; children)
                 walk_account_tree(&child, ancestor_flags | 
account.flags);
         }
````

The problem is that at some point, the verifier starts spewing 
bogus error messages about what it is seeing in the tree. Oddly, 
putting in debugging writelns results in the error messages not 
occurring -- a Heisenbug.  But working with gdb, I found that the 
account structs after the error messages start are zeroed. 
Turning on gc profiling tells me that 3 gcs have occurred. 
Disabling the gc results in the program running correctly -- no 
error messages (and I know the database has no errors because the 
C version, which has been around for awhile, confirms that the db 
is well formed).

I could post a PR, but I'm not sure that this is a bug. It could 
easily be a misunderstanding by me of D and its memory 
management. So I thought I'd try this post first, hoping that one 
of you who knows the language better than I do could point out a 
problem with my code. I do need to resolve this or abandon this 
project.

Thanks in advance for any help.


More information about the Digitalmars-d mailing list