Jump to content

Dalija Prasnikar

Members
  • Content Count

    1148
  • Joined

  • Last visited

  • Days Won

    106

Everything posted by Dalija Prasnikar

  1. Thanks, that helps and your issue is accessible now.
  2. 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
  3. 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.
  4. 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.
  5. 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.
  6. 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
  7. 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.
  8. Dalija Prasnikar

    ifthen strange return value !

    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.
  9. Dalija Prasnikar

    ifthen strange return value !

    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.
  10. Dalija Prasnikar

    ifthen strange return value !

    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.
  11. Dalija Prasnikar

    ifthen strange return value !

    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.
  12. Dalija Prasnikar

    Dynamic array used as a queue. Memory fragmentation?

    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.
  13. Dalija Prasnikar

    Devin AI - Is it already happening?

    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
  14. Dalija Prasnikar

    Devin AI - Is it already happening?

    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.
  15. Dalija Prasnikar

    Delphi 12.1 TCurlHTTPClient

    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.
  16. Dalija Prasnikar

    Thread leaks report (FastMM4)

    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.
  17. Dalija Prasnikar

    Thread leaks report (FastMM4)

    Sorry, I misunderstood then.
  18. Dalija Prasnikar

    Thread leaks report (FastMM4)

    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.
  19. Dalija Prasnikar

    Thread leaks report (FastMM4)

    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.
  20. Dalija Prasnikar

    Thread leaks report (FastMM4)

    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.
  21. Dalija Prasnikar

    Thread leaks report (FastMM4)

    The above code is fine. Free can be called on nil object reference. Testing whether it is assigned before calling Free is redundant.
  22. Dalija Prasnikar

    Threadvar "per object"

    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.
  23. Dalija Prasnikar

    Threadvar "per object"

    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.
  24. Dalija Prasnikar

    Threadvar "per object"

    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.
  25. Dalija Prasnikar

    Quality Portal going to be moved

    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.
×