

JonRobertson
-
Content Count
289 -
Joined
-
Last visited
-
Days Won
7
Posts posted by JonRobertson
-
-
7 minutes ago, havrlisan said:This would be a whole lot easier if Delphi had such a feature. Is it that hard to implement that?
Give it a shot and let us know.
-
1
-
-
1 hour ago, David Schwartz said:If you just have any random form that's got edits and grids and checkboxes and whatnot on it, and they are NOT DB-aware controls, then what do you do?
The data shown and potentially edited on a form comes from somewhere. So I populate the controls from the source and update if/when the user makes changes. If this is in the app with the base form and UpdateUIState implementation I described, I am still able to override methods like UpdateUIState for that form, that code doesn't care about a dataset. Another option is to use LiveBinding, although I've avoided LiveBinding myself.
1 hour ago, David Schwartz said:This wide disparity between forms that are used for interacting with DBs that have DB-aware controls on them vs. those that don't -- because you're not using DB -- has always perplexed me with Delphi.
Just with Delphi? Do you use other languages with frameworks that provide a cleaner solution?
22 minutes ago, Tom Chamberlain said:We force the users to click an Edit button to change 99% of any data and then an Save or Cancel button.
The projects that I currently maintain do this as well. Although I am not a fan of requiring extra mouse clicks. It is easy to detect once a user has changed data and require the user to click Save or Cancel before closing the form.
-
One suggestion would be to use a timer that is reset in OnDataChange. I've done something similar when implementing an incremental search, using the OnChange event of a TEdit for example.
-
7 minutes ago, Willicious said:"Clear;" is called from Clone. But, it isn't in the call stack (not directly, anyway). So, (and this is possibly one of those noobish questions), without prior knowledge of where "Clear" is being called, how can the call stack be used to trace this by itself?
Perhaps it can't without knowledge of the helper class TListHelper. Although you were able to trace back to the point of code where Clear was called and it was shown in your screenshot.
-
1 minute ago, Anders Melander said:This means that you can catch the destruction of a TGadgetAnimation by overriding the TObjectList<T>.Notify method
Thanks Anders.
This approach is should be used rather than the one I posted.
-
1
-
-
23 minutes ago, Willicious said:It's still not 100% clear how we got to the "Free" call, though... I've highlighted the most recent thing that isn't in System.Generics
TGadgetAnimations is a TObjectList that holds a list of TGadgetAnimation:
TGadgetAnimations = class(TObjectList<TGadgetAnimation>)
There are multiple instances of TGadetAnimations created here:
constructor TGadgetMetaInfo.Create; var i: Integer; begin inherited; for i := 0 to ALIGNMENT_COUNT-1 do begin fVariableInfo[i].Animations := TGadgetAnimations.Create;
The TObjectList.OwnsObjects property defaults to True and is not set to False for any instance of TGadgetAnimations. This means that TGadgetAnimations will call Free on the instances of TGadgetAnimation that it holds (which are added by the call to Add).
The TObjectList.Clear method will remove all instances of TGadgetAnimation that were added to that instance of TGadgetAnimations. Since OwnsObjects is True, calling Clear will also call Free on each instance.
When AddPrimary is called the first time for the instance, it assigns a reference to TGadgetAnimation to fPrimaryAnimation.
procedure TGadgetAnimations.Clone(aSrc: TGadgetAnimations); var i: Integer; NewAnim: TGadgetAnimation; begin Clear; NewAnim := TGadgetAnimation.Create(aSrc.PrimaryAnimation.fMainObjectWidth, aSrc.PrimaryAnimation.fMainObjectHeight); NewAnim.Clone(aSrc.PrimaryAnimation); AddPrimary(NewAnim); <-- This will assign fPrimaryAnimation if it is not assigned.
When Clone is called, it calls Clear, which frees the TGadgetAnimation instances that were previously created. But, it does not clear the fPrimaryAnimation reference, which is now pointing to unallocated memory.
Use the solution posted by Anders of overriding the Notify method.
-
1
-
-
8 minutes ago, Anders Melander said:FWIW, it can be set through the constructor too.
I also did not see any place where those particular object lists are created with Create(False)
-
7 hours ago, Kas Ob. said:as for the UnicodeString leak, it might be simply a confusion/confliction in madshi with MemoryManager
16 hours ago, Anders Melander said:My guess is that it's the TGadgetAnimation.fName string which is leaked (based on the string content and the call to UpperCase) but that it a bit strange because strings are reference counted and it's usually pretty impossible to leak them.
If TGadgetAnimation is not being freed, then it would have a reference to fName and the string would also be a leak.
-
7 hours ago, Kas Ob. said:i can't figure out where "GadgetAccessor: TGadgetMetaAccessor;" is freed
GadgetAccessor is assigned by the result of GetInterface. GetInterface creates the TGadgetMetaAccessor and assigns the reference to the FInterfaces array:
function TGadgetMetaInfo.GetInterface(Flip, Invert, Rotate: Boolean): TGadgetMetaAccessor; var i: Integer; begin i := GetImageIndex(Flip, Invert, Rotate); if fInterfaces[i] = nil then fInterfaces[i] := TGadgetMetaAccessor.Create(self, Flip, Invert, Rotate); <-- Created reference assigned to fInterfaces Result := fInterfaces[i]; end;
TGadgetMetaInfo.Destroy loops through fInterfaces and calls Free on each:
destructor TGadgetMetaInfo.Destroy; var i: Integer; begin for i := 0 to ALIGNMENT_COUNT-1 do begin fVariableInfo[i].Animations.Free; fInterfaces[i].Free; end; inherited; end;
Despite the misleading names of GetInterface and fInterfaces, these are not Delphi interfaces. TGadgetMetaAccessor is a class derived from TObject.
-
4 minutes ago, JonRobertson said:I do not see TGadgetAnimations in that code.
Never mind, found it. TGadgetAnimations is a class of TObjectList. TObjectList has a property named OwnsObjects that is True by default. Unless OwnsObjects is set to False, TObjectList will call Free to release all objects that are added to it. See the documentation for TObjectList.OwnsObjects.
The only place in the SupperLemmix code where I see OwnsObjects set to False is here:
fTalismanButtons.OwnsObjects := false; // Because TFLevelSelect itself will take care of any that remain
-
48 minutes ago, Willicious said:fPrimaryAnimation doesn't get freed, and PrimaryAnimation (property referring to fPrimaryAnimation) doesn't get freed. NewInstance and NewAnim also don't get freed. I honestly don't know where to start.
fPrimaryAnimation is likely only a reference to which animation is currently the primary animation.
TGadgetAnimations adds NewAnim to a list of some kind (see the calls to Add(NewAnim) and Add(aPrimary). I suspect TGadgetAnimations is responsible for freeing all animations that are added.
Is this still SupperLemmix? I downloaded SupperLemmix source just now from https://github.com/Willicious/SuperLemmixPlayer and I do not see TGadgetAnimations in that code.
-
12 minutes ago, Attila Kovacs said:Is your question technical?
Yes. Several questions, about the Database Comparer VCL components.
I downloaded the trial and samples of Database Comparer. With the prebuilt DBComparerDemoAdo, I attempted to compare two versions of one of our databases. The result was "Update script is empty" even though there are certainly differences in the schema of the databases.
There are some messages in the log indicating an issue, such as "ambiguous column" and "field not found". However there is no additional information to give insight, such as the DB objects that triggered the errors.
I hoped that "The trial version can operate inside Delphi / C++Builder IDE only, all other features are completely available without any restrictions" was accurate. There is no mention on the download page of other restrictions. The trial version appears to be limited to extracting only a few DB objects.
The help file is unhelpful on most topics, for example:TCustomScriptExtract.ScriptFileNames property ScriptFileNames : TStrings;
A vast majority of the help topics are like this, lacking any description aside from the Pascal definition. Without source, it is difficult to determine the capabilities without better documentation.
One of the most important capabilities that I need to test is how well the components handle dependencies between database objects. What order are objects created? If there are stored procedures or functions that depend on other stored procedures or functions, are these created in the correct order so the creation scripts do not fail?
How can I iterate through DBStructure.Metadata properties (such as Tables, Views, and Procedures) by name? I don't see a way to get a list of the names of the objects that were extracted, a count of the objects, or a way to iterate them by index. If I have a list of table names, how do I use .Tables['MyTable'] to get the CREATE script? I've tried .Body, .CurrentDefinition, .SourceDefinition, .Text, and .SQLExec (to get to .SQLExec.Statements, but .SQLExec is nil).
I greatly appreciate any insight you or anyone else can provide. I need to make a recommendation on purchasing either Database Comparer VCL, Delphi HTML Component Library (primarily for the SQL Library components), or writing my own, which I started investigating today.
-
20 minutes ago, Sherlock said:Assuming they really are based in the US
I doubt it. The domain register is in Germany and the registered name servers are in Russia.
-
Does anyone actively use Clever Components?
I downloaded a trial last week and opened a ticket with questions on Monday. There has been no response or update on my ticket.
Is there an alternate way of contacting support aside from their ticket system?
Thanks
-
-
The Assign method is introduced in TPersistent. All well-written components should override the Assign method. I believe this dates back to Delphi 1.
-
5 minutes ago, Lajos Juhász said:I hope one day they will change their mind on this matter. IMHO even when migrating db related components this would be useful.
Or provide the source (not open source, just source like the RTL/VCL source) to active subscribers so we can adapt it as we need. I added a comment to the RSP but I probably need to create a new QP request since mine was closed as resolved.
-
On 6/13/2024 at 9:22 AM, Lajos Juhász said:Unfortunately this is not implemented yet. You would have to enter a QP request.
Resolved: Works as Expected.
Given reFind is a tool mostly focused on migration to FireDAC, we don't plan expanding it to support other automatic processing scenarios...
-
4 minutes ago, Anders Melander said:There's a more lightweight and faster alternative available in the RTL of recent Delphi versions
5 minutes ago, Anders Melander said:because people didn't know what they were doing
Our "issue" at the time was RTL code. Specially in a DCOM based MIDAS/DataSnap server that created a thread for each user connection. Once the DataSnap server had over 100 users connected, it would frequently lock up due to a deadlock with GlobalnameSpace.
However, the contributing factor was we were doing "too much" in RemoteDataModuleCreate, which extended the amount of time that GlobalNameSpace was locked. We also had multiple TRemoteDataModules due to the size of our app. While I don't disagree with your assertion of "people didn't know what they were doing", it wasn't because we were misusing TMREWS. We never used it directly in our code.
My apologies for hijacking the thread. I'll stop now.
-
3 minutes ago, Anders Melander said:Search broken again?
Nope. It returns results like
On 1/27/2019 at 4:33 AM, dummzeuch said:It does use various instances of TMultiReadExclusiveWriteSynchronizer which, if I remember correctly, was broken in several RTL versions. So using that class might not have been the best decision.
Quoteit is terribly slow. So slow that it is actually almost never OK to use it. If a protected area of code is short, then it is almost always better to use a simple critical section for synchronization.
Quoteit appears there have been some major historical issues with TMultiReadExclusiveWriteSynchronizer but there’s no clear indication of whether this is still the case
Numerous posts about TMREWS having issue and asking if those were fixed. A few posts suggesting an alternate solution.
I trust members of Delphi-Praxis more than most other online resources. So I thought I'd ask.
-
3 hours ago, Dalija Prasnikar said:If you share other data within that instance between threads then any such access should also be protected by a lock
Does anyone use TMultiReadExclusiveWriteSynchronizer? The application team I was on 20 years ago had some problems with it in D6. But I see that the VCL still uses it for GlobalNameSpace (for Windows anyway).
-
7 minutes ago, Anders Melander said:Simply because it looks nice.
Reminds me of one step forward, two steps backwards.
-
2 hours ago, chkaufmann said:My application has 1-n objects of type TBSItemProvider
Is any instance of TBSItemProvider accessed by multiple threads?
-
4 hours ago, Willicious said:It's narrowed down to being a problem with TProjectile, which doesn't have a destructor. However, I implemented a destructor and this doesn't fix the memory leak
Classes do not need a destructor to be destroyed/freed. A class needs a destructor if it allocated other objects or memory that it should free or there is other cleanup it needs to do before being destroyed.
If an object is not being freed, adding a destructor would not fix the issue.
4 hours ago, Willicious said:Does it open a dialog or spit out a text file? Or something else?
Read the comments in FastMM4Options.inc. Specifically:
{Set this option to log all errors to a text file in the same folder as the application. Memory errors (with the FullDebugMode option set) will be appended to the log file. Has no effect if "FullDebugMode" is not set.} {$define LogErrorsToFile} {Set this option to log all memory leaks to a text file in the same folder as the application. Memory leak reports (with the FullDebugMode option set) will be appended to the log file. Has no effect if "LogErrorsToFile" and "FullDebugMode" are not also set. Note that usually all leaks are always logged, even if they are "expected" leaks registered through AddExpectedMemoryLeaks. Expected leaks registered by pointer may be excluded through the HideExpectedLeaksRegisteredByPointer option.} {$define LogMemoryLeakDetailToFile}
It has been a while since I did this. I found a post on SO for a reminder. Based on that post, copy FastMM4Options.inc to your project folder. Edit the .inc file and remove the period from {.$define FullDebugMode}
Do a full build of the project and any leaks should be written to a text file with additional information about the object leaked and when it was allocated.
-
1
-
Tool to sort units used in project by dependency
in Delphi IDE and APIs
Posted
Yes, it is noticeable. My last four projects have been migrating applications from Delphi 7 to 11.3. There were dozens of units referenced that could be either moved to implementation or removed completely. I've been able to get rid of numerous circular dependencies. Although the compile time reduction is not huge, it is noticeable even on a 200K loc project.
Sadly, it takes Azure DevOps longer to check out the repo than building the source.