#1 2019-11-06 14:59:12

ertank
Member
Registered: 2016-03-16
Posts: 163

DynArrayLoadJSON access violation

Hello,

Using Delphi 10.3.2, targeting Win32 executable.

I have demo code at https://pastebin.com/wqdBqRmT

When I run it I get access violation in SynCommons.pas:55273

        D^ := P^; // 3 stages pipelined process of unescaped chars

Synopse commit version is: 1.18.5037

I get same error at same line (line no 54907 this time) using latest codes on GitHub, too. That code Synopse commit version is: 1.18.5448

I am not sure if it is me doing something wrong. I know that I can successfully de-serialize identical json string using an alternative record based library. I do want to use mORMot.

So, I am posting here to see if there is anything to check in mORMot.

Any help is appreciated.

Thanks & regards,
Ertan

Last edited by ertank (2019-11-06 15:16:27)

Offline

#2 2019-11-07 08:48:34

pvn0
Member
From: Slovenia
Registered: 2018-02-12
Posts: 210

Re: DynArrayLoadJSON access violation

Very nice demo!

Instead of :

Pointer(LJson)

try

@LJson[1]

Best regards!

Offline

#3 2019-11-07 09:02:39

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: DynArrayLoadJSON access violation

It works as suggested.

Interesting. I have legacy code about 3 years old working just fine using Pointer() with earlier versions of mORMot:

DynArrayLoadJSON(Taxes, Pointer(sRaw), TypeInfo(TStTaxRatesString));

I cannot say I am good at pointers. I wonder why one works and not the other?

Offline

#4 2019-11-07 09:25:55

pvn0
Member
From: Slovenia
Registered: 2018-02-12
Posts: 210

Re: DynArrayLoadJSON access violation

If you look at SynSelfTests (part of TestSQL3 project) you will see Pointer() is used all over the place including with DynArrayLoadJSON, and that seems to work just fine so I guess there's a specific compiler directive that enables such type casting.

Personally I prefer the more explicit approach.

Last edited by pvn0 (2019-11-07 09:26:58)

Offline

#5 2019-11-07 10:52:12

pvn0
Member
From: Slovenia
Registered: 2018-02-12
Posts: 210

Re: DynArrayLoadJSON access violation

Ok, never mind about compiler directive, the reason your demo fails is because in your case, LJson is not actually a unique string.

See https://pastebin.com/TLTZkDap

Once LJson is made a unique string with ref count >=1, then such pointer type casting will work but I don't recommend it.

Better to use UniqueRawUTF8(LJson) instead of Pointer(LJson) or directly @LJson[1] if you don't care about FPC compatibility.

Last edited by pvn0 (2019-11-07 11:20:35)

Offline

#6 2019-11-07 14:09:24

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,239
Website

Re: DynArrayLoadJSON access violation

This is as expected.
You are missing one point: your string is in read/only memory.
Whereas in the TestSQL3.dpr project, it uses pointer() for read/write strings in memory - strings which have been allocated from the heap.

In your code:

LJson := JsonToDeserialize;

put a reference to a read-only constant string - with refcount = -1.
This is what the compiler does for constants: no memory copy nor heap allocation, just reference of its own read-only binary.


And DynArrayLoadJson() modifies the buffer in-place (adding #0 when needed).
So it tried to write some read-only memory - and the Access Violation appears.

By calling UniqueRawUTF8(LJson), you will ensure that the LJson string is read/write.

Offline

#7 2019-11-07 14:18:01

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,239
Website

Re: DynArrayLoadJSON access violation

I have just make it more obvious in the comments/documentation.

And introduced a new overloaded DynArrayLoadJSON() function which will make a copy of the input buffer.
See https://synopse.info/fossil/info/bd63059e2f

Offline

#8 2019-11-08 08:59:44

ertank
Member
Registered: 2016-03-16
Posts: 163

Re: DynArrayLoadJSON access violation

ab wrote:

I have just make it more obvious in the comments/documentation.

And introduced a new overloaded DynArrayLoadJSON() function which will make a copy of the input buffer.
See https://synopse.info/fossil/info/bd63059e2f

I like new overload function more because of its Boolean return makes it easier to understand if result is a success or not.

Thank you.

Offline

Board footer

Powered by FluxBB