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