Visual D 0.50.0-beta1 released
Rainer Schuetze
r.sagitario at gmx.de
Sun Jul 28 11:45:21 UTC 2019
On 28/07/2019 06:59, Bert wrote:
> On Wednesday, 24 July 2019 at 15:32:01 UTC, Rainer Schuetze wrote:
>>
>>
>> On 24/07/2019 08:33, Bert wrote:
>>> On Tuesday, 23 July 2019 at 20:57:17 UTC, Rainer Schuetze wrote
>>>> As it turned out, the problem was (again?) a false entry in the class
>>>> name cache that was added when an invalid pointer (including null) was
>>>> evaluated (and its dynamic was tried to be determined). Stupid bug, but
>>>> that happens.
>>>>
>>>> You can try the fixed version of MagoNatCC.dll from
>>>> https://ci.appveyor.com/project/rainers/mago/build/artifacts
>>>
>>> That worked! I still find it very odd that it would exhibit it with
>>> irrelevant lines of code removed. Was that changing the cached
>>> version or something? Remember I basically have several Q's in my
>>> program all virtually identical and some would work and others wouldn't.
>>>
>>> Could you post some of the code that you fixed(or I guess push it to
>>> master) when you get a chance... I'm just curious to what it looks
>>> like. While such bugs are very annoying and better coding methods
>>> should be used, I imagine that this type of scenario for interface
>>> resolution is probably well localized and this would probably be the
>>> last bug fix for it? If not maybe some logging could be implemented.
>>> Interfaces should always be resolvable so if the code fails it is a
>>> bug in Visual D and having it logged in some way might help future
>>> cases.
>>
>> The bugfix commit is
>> https://github.com/rainers/mago/commit/9801da089a4b4e9ffa8f1442f4b0aff5852d5fa9?w=1.
>>
>>
>> The problem was that evaluating the dynamic type of any uninitialized
>> or null class/interface pointer could overwrite a previously evaluated
>> entry in the vtbl->class name cache depending on what happens to be in
>> an uninitialized local variable.
>>
>> Hopefully the last bug in that area, but you never know. Adding
>> logging would help diagnosing bugs but would have to be more global.
>
> Thanks.
>
> I can't imagine though why adding a simple field would screw the code up.
>
> e.g.,
>
> class X {} // works.
> class Y { int y; } // fails.
>
This wouldn't have failed, int needs a class/interface member, e.g.
class X
{
Q q; // non-null
I c; // null
Q s; // non-null
}
> I would think that such things would have no effect on the pointer value?
>
> Can you explain to me, for my own edification, why removing those
> non-essential lines would produce the effect?
>
The bug basically was similar to
// global cache
string[void*] mapVtblToClassName;
void showX(X x)
{
void* vtbl;
string classNameq;
bool rc = ReadProcessMemory(x.q, vtbl); // reads vtbl-ptr
if (rc)
{
if (vtbl in mapVtblToClassName)
{
classNameq = mapVtblToClassName[vtbl];
goto Lnext;
}
classNameq = getClassNameFromVtbl(vtbl); // Q
}
mapVtblToClassName[vtbl] = classNameq;
Lnext:
string classNamec;
rc = ReadProcessMemory(x.c, vtbl); // fails, vtbl unchanged
if (rc)
{
// same as above...
}
mapVtblToClassName[vtbl] = classNamec; // overwrites entry for Q
}
Next time a Q is evaluated, the determined class name will be empty.
More information about the Digitalmars-d-ide
mailing list