-
Content Count
1148 -
Joined
-
Last visited
-
Days Won
106
Everything posted by Dalija Prasnikar
-
Delphi bug reports or feature requests to "vote"/comment for (important, fatal etc)/
Dalija Prasnikar replied to Tommi Prami's topic in Delphi IDE and APIs
Thanks, that helps and your issue is accessible now. -
Delphi bug reports or feature requests to "vote"/comment for (important, fatal etc)/
Dalija Prasnikar replied to Tommi Prami's topic in Delphi IDE and APIs
I don't know if you can change that now, but when posting issue you need to use Share with Embarcadero customers to make it visible to others. See https://dalijap.blogspot.com/2024/04/delphi-121-new-quality-portal-released.html -
Delphi bug reports or feature requests to "vote"/comment for (important, fatal etc)/
Dalija Prasnikar replied to Tommi Prami's topic in Delphi IDE and APIs
No. Please don't post existing bug reports to the new tracker as they already exist in the internal tracking system and doing so duplicates the issues and only creates more unnecessary work. Also ne tracking system does not support voting. There are zero benefits for anyone involved. -
Gaining access to private class vars of an implementation class
Dalija Prasnikar replied to Eric Grange's topic in RTL and Delphi Object Pascal
The problem is that Embarcadero provides base framework classes that satisfy very narrow usage and are not properly open for extension. Sometimes you need to change literally one line, to get the needed behavior, but there is no way to do that properly. So you need to resort to hacking into those classes. Protected opens up the class for needed extensions and still protects casual users from using implementation details and does not break encapsulation. Yes, if the implementation changes, you may need to update your code to match the changes, but you would need to do that regardless. Private is major PITA. -
Custom Managed Records and Default(T)
Dalija Prasnikar replied to rgdawson's topic in Algorithms, Data Structures and Class Design
Yes, sorry. I missed the context you are replying to. We agree on the rest, and that was the point of my example. To show that custom managed are initialized/finalized even if not used and that there is extra initialization for Default call on implicit temporary variable. And compiler should be smart enough not to require any temporary variable at all. In any way thing is broken. -
Custom Managed Records and Default(T)
Dalija Prasnikar replied to rgdawson's topic in Algorithms, Data Structures and Class Design
Because whole point of custom managed records is automatic initialization/finalization. So if you merely declare such record as local variable and you don't ever use it, its initialization and finalization routines will run. Running following code makes the issue more obvious. type TMyRec = record x: Integer; class operator Initialize(out rec: TMyRec); class operator Finalize(var Dest: TMyRec); class operator Assign(var left, right: TMyRec); end; class operator TMyRec.Initialize(out rec: TMyRec); begin Writeln('init'); end; class operator TMyRec.Finalize(var Dest: TMyRec); begin Writeln('finalize'); end; class operator TMyRec.Assign(var left, right: TMyRec); begin Writeln('assign'); end; procedure Main; var r: TMyRec; begin r := Default(TMyRec); end; begin Main; end. If assignment is commented out then result will be init finalize But running code as-is will result with: init init init assign finalize finalize -
How to correctly write a universal project for both Windows and Andorid platforms?
Dalija Prasnikar replied to dmitrybv's topic in FMX
One thing you would want to do is use single form as a container and organize all other forms as frames. Working with multiple forms on mobile is major PITA and docking frames in that main form container is much simpler for switching between views. You can still have multiple forms and dialogs on Windows if needed where you will dock the same frame used in mobile, on the separate container form. -
ifthen strange return value !
Dalija Prasnikar replied to bravesofts's topic in Algorithms, Data Structures and Class Design
Er... no. It does not matter how correct is the input, the output can still be outmost garbage when it comes to the correctness, it will just sound nice. Also, if you don't know whether some statement is correct or not how can you verify the output. For instance AI can say "Local variables are automatically initialized" and "Local variables are not automatically initialized" If you don't know which of those statements is true, you will not be in position to verify. You cannot even check with code, because local variable can accidentally occupy memory that was zero at the time, so it may seem like the first statement is true, while it is not. It does not matter how often it is correct (the best AI will be wrong in over 20% of responses, which is far from insignificant), it is about inability of a person who does not know something to determine whether response is correct or not. Even merely translating and rewording of correct content can result with incorrect output. Some examples how AI can lie to you: https://github.com/mdn/yari/issues/9208 and MS copilot demonstration video around 38 minutes. -
ifthen strange return value !
Dalija Prasnikar replied to bravesofts's topic in Algorithms, Data Structures and Class Design
I would suggest that you don't use ChatGPT or any other AI for writing or explaining the code. While it may give you correct results at times, quite often it will be completely wrong and you will have no idea whether what it said is correct or not. -
ifthen strange return value !
Dalija Prasnikar replied to bravesofts's topic in Algorithms, Data Structures and Class Design
It doesn't work like that. LObj is reference type. That means it consists of two parts. LObj variable itself is merely a pointer (address) that will point to the object instance when it is allocated on a heap. All local variables are allocated on stack, not heap. So when you declare local variable the memory for the pointer is automatically allocated on stack when FormCreate is called. Stack memory is not automatically cleared, so whatever values were there, they will remain. Only managed types local variables will be automatically initialized. When you create object and assign it to that variable then created instance will be allocated on a heap and address of that memory location will be stored in LObj variable. This behavior is same on all platforms. However, until Delphi 10.4 Delphi mobile platforms had ARC compiler where objects were automatically managed and local object variables were automatically initialized on those platforms. -
ifthen strange return value !
Dalija Prasnikar replied to bravesofts's topic in Algorithms, Data Structures and Class Design
LObj is local variable and it is not initialized. That means it will hold some random value (garbage). This is why it can show that object is allocated when it is actually not. You need to initialize it (to nil, or assign some object instance to it) before you can call your function. -
Dynamic array used as a queue. Memory fragmentation?
Dalija Prasnikar replied to A.M. Hoornweg's topic in RTL and Delphi Object Pascal
If you are frequently adding/removing items from array and the maximal occupied memory is not an issue, I would use TList<T> instead of dynamic array which supports Capacity. Set the Capacity to the maximum number of elements you are expecting (if there are more underlying dynamic array will automatically grow). That will prevent frequent allocations/deallocations and improve performance. You may also use TQueue<T> which might be fit for your needs. Whole array needs to be allocated in one place so there will be no memory fragmentation just because of that array reallocations. -
Devin AI - Is it already happening?
Dalija Prasnikar replied to FreeDelphiPascal's topic in General Help
I am not talking about what you put in your code repository and where and how you host it. I am talking about full AI integration with IDE where you may open security sensitive code in the IDE which then might be sent to AI and end up in training data without your knowledge. And you don't even have to open it. It may just be a part of your project where AI will go through your complete data to be able to give you relevant explanations and completions. Similar to https://economictimes.indiatimes.com/news/international/us/is-google-gemini-ai-accessing-your-google-drive-files-heres-what-you-can-do-about-it/articleshow/111788643.cms?from=mdr -
Devin AI - Is it already happening?
Dalija Prasnikar replied to FreeDelphiPascal's topic in General Help
Once something is integrated, there is always a possibility of bugs. You have a setting that says you are not allowing some feature, but the bug creeps in and the feature ends up enabled behind your back. Another problem is that with AI, companies have incentive to make "bugs" and use anything they can get their hands on for training. Your data is the product. So while you may be fine with some parts of your code being used for training, there will be parts you will want to keep secret for security reason (if nothing else, various API keys and similar), but if you have AI integrated in the IDE, you can never be sure which parts of your code will be used for training and which ones are not. For some people and companies the security concern is real and even slight possibility that some parts of their code or other information can leak through AI can be a huge risk. -
Delphi 12.1 TCurlHTTPClient
Dalija Prasnikar replied to nickneykov's topic in Network, Cloud and Web
You still need libcurl.dll if you want to use TCurlHTTPClient. It is a wrapper class for curl, but the curl itself is in the DLL. TCurlHTTPClient is THTTPClient descendant so you can easily switch between different HTTP implementations without changing other code. -
Raising exceptions in constructor never ever lead to memory leaks. Only if the code in destructor is bad and is not able to clean up partially initialized object instances. such situations may look like raising exception in constructor is at fault, while actually it is the destructor that needs to be fixed in such case.
-
Sorry, I misunderstood then.
-
Sorry, but @Der schöne Günther is correct. If the exception is raised in the constructor, then destructor will be called to perform cleanup on already allocated stuff. Unless the destructor is broken (badly written), there will be no memory leaks. That is why destructor needs to be able to work properly on partially constructed object instances, without raising any additional exceptions. Exceptions raised within the destructor will cause irreparable memory leaks. Best practice is that you can do whatever you want in the constructor in any order you whish (provided that you don't access things that are not yet created) and destructor must never raise an exception. Again you can also call inherited destructor in any order if you need to do that for some reason.
-
There are none. Free can always be called on nil instance. Running other code in the destructor where it is assumed that instance is not nil would require checking whether instance is nil before calling that code. In such code Free is often put within the Assigned block, not because it needs to be there but to avoid additional potentially unnecessary call when the instance is nil.
-
There are some issues in your code. Your constructor can be simplified - the inherited thread constructor will handle raising exception if thread cannot be created. Also it does not make sense to construct suspended thread and then starting it in constructor because constructor chain will complete before thread runs because non suspended thread is automatically started in AfterConstruction method, not before. Additionally, your code constructs sock after you have called Resume, where it would be possible for thread to access instance which is not created yet (this is very slight possibility, but it is still possible). You should also destroy all objects in destructor, after you call inherited destroy, which will guarantee that thread is no longer running at that point and preventing access to already destroyed sock object. Next, since you are creating self destroying thread, such threads don't have proper cleanup during application shutdown and will just be killed by OS if they are still running at that time. If that happens there will be memory leaks. Explicitly releasing the thread would be better for controlled shutdown and thread cleanup.
-
The above code is fine. Free can be called on nil object reference. Testing whether it is assigned before calling Free is redundant.
-
Threadvar "per object"
Dalija Prasnikar replied to chkaufmann's topic in Algorithms, Data Structures and Class Design
Word of caution, TLightweightMREW is not merely a lightweight equivalent of TMultiReadExclusiveWriteSynchronizer as it has different behavior. Most notably, write lock is not reentrant on TLightweightMREW and acquiring write lock from the same thread twice will cause deadlocks on Windows platform and will raise exception on other platforms. When it comes to TMultiReadExclusiveWriteSynchronizer it is implemented as MREW only on Windows and on other platforms it is exclusive lock. -
Threadvar "per object"
Dalija Prasnikar replied to chkaufmann's topic in Algorithms, Data Structures and Class Design
You would need to call method at the beginning code that runs in a thread that would add that thread ID into dictionary and create cache instance for that key. At the end of the thread code you would also call method that would be responsible for removing that key and cache from the dictionary. This add/ remove logic should be protected by some locking mechanism contained within TBSItemProvider instance and protected with try...finally block so that cleanup is done in case code in between raises an exception. If you share other data within that instance between threads then any such access should also be protected by a lock, unless all threads are only reading the data. -
Threadvar "per object"
Dalija Prasnikar replied to chkaufmann's topic in Algorithms, Data Structures and Class Design
Those are fields in a class, threadvar is only supported for global variables. There is not enough context around what you are trying to do, so it is hard to say what is the most appropriate solution. From how it looks now, I would say that what @David Heffernan proposed looks most suitable. You would have to create and remove items in the dictionary when thread is created and destroyed. Another question is, are you sharing other data within TBSItemProvider instance between threads which sounds like you are doing, and what kind of protection you have around that data. If it is not read only then sharing data is not thread-safe. -
Quality Portal going to be moved
Dalija Prasnikar replied to Uwe Raabe's topic in Community Management
I don't know the details of their setup or the migration process, but it definitely took much longer than it was initially expected. If I remember correctly this coincided with the server outage, so it is possible that this also had an impact. This is right on the mark.