Jump to content

Dalija Prasnikar

Members
  • Content Count

    1129
  • Joined

  • Last visited

  • Days Won

    102

Everything posted by Dalija Prasnikar

  1. Dalija Prasnikar

    Is Delphi's HTTPRIO thread-safe?

    It is not thread safe. You cannot share one instance among threads.
  2. Dalija Prasnikar

    Exception classes implementing interfaces

    This sounds like a solution in search of a problem. As previously mentioned there are better options.
  3. Dalija Prasnikar

    debug IOS using instruments Leak detector

    There is no "unified" handling of the TOCLocal instances, because what you need to do depends on how you got the instance. So that part seems fine. destructor TFMXTextRange.Destroy; begin FStart.free; // added by bb FEnd.free; // added by bb inherited; end; As far as TFMXTextRange is concerned there should definitely be calls to Free, niling is redundant. But, those classes are reference counted, so they should have never been stored in object references to begin with FStart: TFMXTextPosition is wrong (and if they would be stored in interface references then Free would not be needed). This is where those changes in TOCInterfacedObject possibly come to play, to prevent issues with reference counting and allowing instances to be stored in object references. But in that case anything stored in interface reference would be broken. So the whole thing is a bit incomprehensible to me right now, because it also depends on how is each instance stored (interface or object reference), whether Free is called or not. The only way to easily see what is going on is through debugging and I cannot do that right now. Bottom line... FStart.Free and FEnd.Free should have some impact on reducing number of leaks, but it is quite possible that there are other leaks due to changes in TOCLocal. If you put breakpoint at FStart := nil you should be able to see whether TFMXTextPosition.Destroy is called. If it is then, niling is fine. If not, try with FStart.Free. If that calls destructor that is first fix you need to do. If you still have leaks, you can try calling FStart.Release before FStart.Free to explicitly release ObjectiveC object behind it. If you get segmentation fault afterwards, then this is wrong. I am sorry that I cannot be of more help.
  4. Dalija Prasnikar

    debug IOS using instruments Leak detector

    Maybe not.... I haven't looked at iOS since Rio was released and I haven't used it with 10.4 when ARC compiler was removed. There are some weird changes in Macapi.ObjectiveC specifically in TOCLocal class declaration which now uses TOCInterfacedObject. But that requires deeper look and I cannot do that right now, plus I don't have my Mac fully setup to work with Delphi. But, maybe it will give you some clues as where to look. It seems like changes are there to prevent reference counting destroying the object, but in that case there is definitely need for calling Free on anything constructed. Unless compiler is doing some magic behind the scenes for those classes.
  5. Dalija Prasnikar

    LSP - Alexandria

    No, there is no flag. Classic code insight has been completely removed in Delphi 11. I don't know the details, but there were some interference issues that could not be resolved otherwise.
  6. Dalija Prasnikar

    Delphi 11 TRestRequest Failure

    Probably related to this issue https://quality.embarcadero.com/browse/RSP-35341
  7. Dalija Prasnikar

    Calling inherited in Destroy

    Not really. It is the most lightweight list class that can be used there as dynamic arrays don't have capacity which prevents excessive memory reallocations when growing array. Question is, whether the whole algorithm could be implemented in a different way, but that is another story (I am not saying that it can be better as I haven't done any analysis)
  8. Dalija Prasnikar

    Calling inherited in Destroy

    Always call inherited in destructor. I would also add always call inherited in constructor, but if you miss to call constructor that does something, you will know soon enough. If you don't call destructor, you may have leaks which can be much harder to detect later on. This is extremely low level optimization and it makes sense only in some code that will be called a lot, but even then think four times before you write it as changes in class declaration - using different ancestor can break such code badly. I have this kind of optimization in 3 places in my code in my smart pointer, weak and lazy reference implementations. Inherited is there, it is just commented out and there is additional comment explaining why it is there. If anything breaks in TObject, I have only one file to change. But even now, while I am writing this I feel extremely uneasy about that code. So don't do write such code, unless you really have good reason, and don't write it even then.
  9. Dalija Prasnikar

    splitting interface + implementation

    The only thing that includes terms "interface" and "implementation" and that CAN be separated in different files are interface declarations and classes that implement those interfaces and implementing classes will again have interface and implementation part in the unit file itself. If it was Nick's book, it could be Coding in Delphi or Dependency Injection in Delphi, but again you will not find anything there about separating interface and implementation parts of the unit because that cannot be done (besides using include files), only how to use interfaces.
  10. Dalija Prasnikar

    Class Instance vs Object Instance

    Don't ever call NewInstance - this s internal method. https://docwiki.embarcadero.com/Libraries/Sydney/en/System.TObject.NewInstance You should call constructor to create (allocate) new object. vRef := TBaseForm(AFormClass.Create(aOwner)); or you can typecast with as operator which will fail at runtime if the AFormClass is not TBaseForm vRef := AFormClass.Create(aOwner) as TBaseForm; When you declare variable var vRef: TBaseForm; This will only automatically allocate pointer (reference) to your future form - if this is local variable it will be allocated on the stack, if it is field it will be allocated as part of object instance. This is automatic and you don't need to manage memory for that pointer, variable itself. Only when you call constructor actual object instance will be created and allocated - if you create form with owner, that owner will be responsible for releasing its memory. If you pass nil for owner, you need to release it yourself. There is no class instance here, only object instances. Class instance is constructed when you declare class variables in class declaration - and they are automatically allocated and deallocated and there is only single one per class. Again you are not using them in your code. Following is example of class variable declaration. Variable Foo is accessible as TBaseForm.Foo or as vRef.Foo but it will be the same shared integer variable. TBaseForm = class(TForm) public class var Foo: Integer; end;
  11. Dalija Prasnikar

    How to manage feature changes during release cycle?

    This can happen even if you don't use any VCS Not the conflict per-se, but changes in common code if projects are not separated can cause problems and other project may no longer work properly or even compile.
  12. Dalija Prasnikar

    How to manage feature changes during release cycle?

    Yes, of course. Point is that merge conflicts are often used as an argument against branches and to a point branches can escalate problem. For instance single developer developing on single branch will not have merge conflicts, but reckless use of branches can cause issues even for single developer, which often leads to the conclusions that branches are inherently bad, not the how they are used.
  13. Dalija Prasnikar

    How to manage feature changes during release cycle?

    Main issue with branches are merge conflicts. They tend to get worse with time because more code is added and there is potentially more conflict. So naturally, if you have short lived branches there is less possibility for conflicts to emerge. Also continuous delivery focuses on making small incremental changes (which is not always possible) so making small features that don't span across too much code (files) tend to be easily mergeable. Having said that, the lifetime alone actually means nothing. Nor the number of branches. First, you can easily shoot yourself in the foot with the branch old just a few hours, if you change some "hard" to merge file - think something like dproj file. On iOS, macOS that would be storyboards - you don't even need multiple developers to make a mess. So for some types of files, you will need to have specific instructions about who and how can change them without causing issues. Next, it is not how long branch lives, but whether you keep it up to date with other development. If you have branch and you merge it after a year, of course there will be trouble, but not because the branch is year old, but because you didn't keep it up. The most important rule is don't merge, rebase and rebase often. Not only that keeps history cleaner, but you will also have less conflicts - most of the time there will be none or they will be simple to resolve. And of course, in larger teams there has to be some coordination between what is done and when. It makes no sense to start some large refactoring in one part of the code few days before another large refactoring in overlapping area of the code is finished. It is better to wait than waste time on merging.
  14. Dalija Prasnikar

    New FMX project dose not launch

    I am not questioning your decision, I am merely explaining why you cannot easily use older Delphi versions for mobile development. No.
  15. Dalija Prasnikar

    New FMX project dose not launch

    I don't know what OS version S21 uses, but 10.2.3 is rather old version. There are API changes in Android every year that can have impact on compatibility. Just changing targetSdkVersion does not generally help, because it is not just about changing the number. When you change that number you are saying that your application supports particular Android OS and its capabilities, while application you are building with old Delphi version will not fully support new OS. This is why for mobile development you need to keep current with latest Delphi as it has added support for newer versions of mobile OS.
  16. Dalija Prasnikar

    Why empty dynamic arrays = NIL?

    I am few dimes short...
  17. Dalija Prasnikar

    Why empty dynamic arrays = NIL?

    True. But that is not the argument for nil string and arrays, on the contrary. I am all for having nullable types built in, together with full language support, but that does not mean I am for changing how strings and arrays work. Nullable types should be wrapper on around those and value types.
  18. Dalija Prasnikar

    Why empty dynamic arrays = NIL?

    But you can have your own implementation. I don't know about C#, but handling strings or arrays in Java is nightmare. You need to check for nil before you can do anything with it. Yes, if you have created it few lines of code before then you don't have, but usually you don't know from where it comes from and you need to check. If I had a dime for every time I though "this string cannot be nil here, so I don't need to check" and then I had exceptions at runtime, I would be on my tropical island right now, drinking pina colada.
  19. Dalija Prasnikar

    Why empty dynamic arrays = NIL?

    If you need that distinction you can always wrap it up in nullable type. Delphi implementation of strings and dynamic arrays is fine as it is. Adding that distinction into array or string itself would only complicate working with strings and arrays with no benefits in most of the code. What would be default value of the array or string? nil or empty? If it is nil, welcome to nil nightmare, if it is empty, you need nullable again, or you would just want the ability to nil after it is initialized to empty. This is the fastest road to hell.
  20. No. I am using Xcode and Android Studio. I am also keeping my eye on Delphi side, but I am not using it for anything beyond some test projects. This is a long story, and originally when Delphi added Android support I couldn't use it because it didn't supported all devices I needed to support so I had to use Android Studio. Also Delphi was less interesting for some projects because it removed 8-bit string support and it was crucial for my codebase because I am using UTF-8 based strings for processing since Delphi 7. For those project(s) it was eventually simpler and cheaper to use Windows tablets than switching to Android. Using Delphi definitely makes sense if you have plenty of common business code. Since unification of memory management and bringing 8-bit strings back, that is now even more viable. It all depends on particular situation. It is hard to give general advice. Of course, switching tools is never easy and once you have significant investment in any toolset it is much harder to justify moving to something else - even if it means using same language and UI for all.
  21. You are overly focusing on Ansi. I am more talking about differences between processing in UTF-8, UTF-16 and UTF-32. Depending on what you are doing you might want to use particular string type to avoid unnecessary conversions. For instance on Linux UTF-8 is most commonly used encoding, it makes sense to load data stored in UTF-8 and process it in UTF-8 before storing it back or sending it to client in UTF-8 encoding. Using UTF-16 string type there is utmost waste or resources. On Windows where Windows API-s use UTF-16 that is much less important and you could use regular string type and don't care. But even on Windows you could have situation where you are not interested in UTF-16 representation and where you will do all processing in UTF-8. So all those types very much make sense.
  22. Don't get me started with Swift... (besides the fact you can use other string types there like NSString and NSMutable string) Original Swift string representation storage was UTF16. Swift string, just like with current Delphi string wastes memory and loading and storing (UTF8 is most common storage encoding) performs conversion. Recently Swift string was optimized and UTF16 was replaced with UTF8- This reduced memory consumption and also increased performance. But that is something that had to be done in compiler. Before that you would either have to live with worse performance or you had to fiddle with C++ strings. And working with Swift strings is often #$%&@! because you cannot do simple things in simple way, because you have to got through Unicode consistency layer. Now it is probably simpler to have single string type (if it is well optimized) but that requires completely different string handling and compiler support. Changing that would have immeasurable impact on existing code. Starting new language fresh and designing it with single string type is possible, but old language that has been built on 50 years old roots cannot change its internals that easily.
  23. Delphi string types not only differ in bitness, but in memory management. I don't know how Python shows data to the APIs, but as I previously said that part usually requires converting data back and forth. Ability to work with particular representation directly enables you to write faster code, to avoid unnecessary conversions. Python does not work on such low level Delphi can. That is why half of libraries that do stuff are written in C or C++
  24. I think that family has too many outliers. It is just bunch of languages grouped together because they share few syntactical elements - but they are not roots, they are just letters of the alphabet.
  25. Some syntactical elements, yes and the fact both have GC. But C# also shares plenty of language concepts with Delphi that don't exist in Java. For instance, properties, records, But my comment was partially a joke, so I am not going to argue about this. Certainly C# and Java share some common ground, way, way more than they both share with C.
×