That happens, when one tries to squeeze in a "simple looking" bug fix....
In 61205 (lines 590 - 599), shouldn't the palette also be treated like Data and Mask.
Yes palette is needed too. Done.
This procedure TRasterImage.LoadFromRawImage is called in Lazarus only once by \components\ideintf\imagelisteditor.pp in function CreateGlyphSplit (which itself is never called) so it is difficult to know, for example, what ADataOwner is supposed to mean.
That was the reason I suggested in https://forum.lazarus.freepascal.org/index.php/topic,45016.msg317235.html#msg317235 April 11, 2019, 03:43:45 pm a Patch using ReallocMem only when ADataOwner=False.
I am not sure about ADataOwner neither. You can suggest additional patches on the bugtracker. Maybe someone who knows the code better will pick it up.
Please changed that, You have actually erased the pointers before calling the FreeData;
You just basically put it back to where it was...!
You need to clean up the existing img^.... You need to call FreeMem on those pointers.
DO NOT nil the pointers and then call Img^.FreeData because it will never free it!
Setting the pointers to NIL before FreeData is full intention.
Normally the target (img^) has probably either no data/mask/palette or different data/mask/palette.
- If it has none, then nothing needs to be done, and the nil setting does not matter.
- if it has different, then the conditions are false, and there is no setting to nil.
=> So those two cases are fine.
- If either one, two or all of data/mask/palette are the same as the source on AImage:
Then calling FreeData *before* setting to nil, would be a problem.
If "img^.Data = AImage.Data" and I call img^.FreeData, then I release the memory.
After that Image.Data is a dangling pointer, and the memory that it points to, can contain any random trash.
Assigning that dangling pointer to img^.Data makes it worse. Copying the trashed content of this memory block to newly allocated memory is not better either.
And worst case the memory was returned to the OS, and it causes a SigSegV.
So if "img^.Data = AImage.Data" and I call img^.FreeData, then I *prevent* that Data from being freed.
I may still have to free the img^.Mask, because for the same Data, there could be a different Mask.
From review of the code:
* With DataOwner = False
The OLD code would always assign copied memory to img^.
The OLD code would leak memory, in some cases.
The NEW code will always assign copied memory to img^.
The NEW code will free the old memory af the target img^, *if* that memory would otherwise be leaked (have no (known) reference left)
* With DataOwner = True
Same as above, but instead of copies, a pointer to existing memory will be made.
DataOwner = True
Means that the memory of the source AImage.Date/Mask/Palette must not (is not allowed to) be freed, as long as the target "img^" is in use.
At the end, only one of the 2 is allowed to free the memory.