Jump to content

A.M. Hoornweg

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by A.M. Hoornweg

  1. A.M. Hoornweg

    The Case of Delphi Const String Parameters

    The reason is, that when S goes out of scope, it decrements the reference count of G. G should only be destroyed when its reference count reaches zero so that action must be atomic.
  2. A.M. Hoornweg

    The Case of Delphi Const String Parameters

    That may very well be true. But when a developer is doing refactoring to make code more legible and concise, IMHO it is a good thing if the parameter list reflects the intended use of the parameters. So if a parameter is intended just for outputting something and not for modifying an existing value, the "out" modifier is clearer than "var". I find "const" parameters confusing at times, especially when passing stuff like arrays. If I pass an array as a const, am I supposed to be able to modify elements or not? The Delphi documentation (link at he bottom) says "... constant parameters are similar to value parameters, except that you cannot assign a value to a constant parameter within the body of a procedure or function..." . I don't want to nit-pick, but I find it very confusing and counter-intuitive that I can modify the array in such a case. Type tintarray=tarray<integer>; Procedure dosomething (CONST a:tintarray); var i:integer; begin for i:=0 to high(a)-1 do a[i]:=random(maxint); end; procedure TForm1.Button1Click(Sender: TObject); var x:tintarray; begin setlength(x,10); //newly allocated space is set to 0 dosomething(x); showmessage(format('%d',[x[0]])); end; http://docwiki.embarcadero.com/RADStudio/Sydney/en/Parameters_(Delphi)#Constant_Parameters
  3. A.M. Hoornweg

    The Case of Delphi Const String Parameters

    Unlike "shortstring", Delphi cannot pass managed types such as strings by value. It is always a pointer. I'm not 100% sure but I think an "out" parameter is like a "promise" to return a value no matter what, and also a promise not to use it for input. The problem being that it is possible to pass the same variable twice and thus circumvent the no-input promise.
  4. A.M. Hoornweg

    The Case of Delphi Const String Parameters

    "Out" parameters of managed types (such as strings, interfaces, dynamic arrays) are initialized before a method is called. The problem only arises because multiple parameters in the method reference the same string. The behavior is correct but very counter-intuitive. It would behave more intuitively if the compiler would issue a UniqueString() for the second/identical parameter.
  5. A.M. Hoornweg

    The Case of Delphi Const String Parameters

    I posted about it before in this forum and was told that it's intended behavior. Admittedly, it's a corner case, but it did happen and cost me a lot of time to figure it out. A compiler warning would have been nice.
  6. A.M. Hoornweg

    grid with expandable area below each row?

    There's also this thingy called "tGridpanel" in Delphi. I have never used it myself though.
  7. A.M. Hoornweg

    From Interbase To Firebird

    How about metadata (access rights) , triggers etc?
  8. A.M. Hoornweg

    The Case of Delphi Const String Parameters

    "Out" parameters are an even bigger can of worms. I had refactored some code recently to use "OUT" parameters instead of VAR parameters (in order to more clearly document the intended use) and it had side effects that were hard to figure out. I thought my debugger had gone bananas. Try single-stepping through this code and watch the values. In hindsight, the cause is clear, but I find the compiler should throw a warning if it encounters such a situation. I now avoid OUT parameters. procedure tform2.test(OUT somestring:String; Defaultvalue:String); begin Somestring:=Defaultvalue; end; procedure TForm2.Button1Click(Sender: TObject); var t:string; begin t:='Testing 1-2-3'; Test(t,t); Showmessage(t); end;
  9. A.M. Hoornweg

    The Case of Delphi Const String Parameters

    TMS FixInsight (a sourcecode analysis tool) flags non-const string parameters as bad practice if these strings are never written to.
  10. A.M. Hoornweg

    Error E2010 incompatile types are same types

    Did you install any software or packages recently that changed your system's "path" variable? The Windows PATH variable has a limited maximum length. If setup routines keep adding entries to it then it may get truncated and all sorts of things on your system stop working properly. Like Delphi not finding its installed BPL's anymore. Happens to me all the time. Some component manufacturers (like TMS) store BPL's in non-standard locations and that regularly causes me headaches for this reason. I really wish component manufacturers would stop doing that.
  11. A.M. Hoornweg

    Images in High DPI, how?

    My current approach is to store all *.PNG files in high resolution inside the resources. I scale them down to the appropriate size when the application starts and the display resolution is known. I use my own scaling routines (using a Lanczos2 filter) but there are lots of libraries that can do the same thing. This approach does not solve the situation of the user having multiple screens in multiple resolutions though.
  12. A.M. Hoornweg

    Year Countsdown

    @emailx45 you're kinda missing the point. Decoding is not the issue here. My point is that a "month" does not have a constant value. So expressing a countdown as "2 months and 5 days left until..." is totally vague. If there is a distance of 29 days between two dates, that distance can be either exactly one month, one month plus a day, one month minus a day or one month minus two days, depending on where in the calendar you are.
  13. A.M. Hoornweg

    Year Countsdown

    There are several pitfalls here. The most important one: months don't have a constant length. For example, assume it is February 14. How many months and days is it until March 13? And until March 15?
  14. Somehow I totally missed this, but in october 2017 Microsoft did a complete U-turn on deprecating OleDB database connectivity. They have even released new OleDB providers for MS Sql Server which will be maintained and updated with the most recent server features. https://blogs.msdn.microsoft.com/sqlnativeclient/2017/10/06/announcing-the-new-release-of-ole-db-driver-for-sql-server/ https://docs.microsoft.com/en-us/sql/connect/oledb/oledb-driver-for-sql-server?view=sql-server-2017
  15. I mean a tool to analyze large existing projects with many units. Maybe something like TMS Fixinsight Pro.
  16. Especially tricky to optimize are hidden managed variables. Delphi creates those when it needs to store intermediate results of managed types [as in tstringlist.add (format('Test %d',[123]))]. It would be great if there were developer tools that would point out the creation of such hidden variables.
  17. Fair enough. You're using the stringlist as an internally shared object, just for saving some time by not having to create/destroy one whenever you need one. You could take that concept one step further by creating a global stringlist pool (a singleton) from which you can request an available tStringlist whenever you need one. That pool could be shared among many objects and you could even make it threadsafe if you want. The problem of having local variables of managed data types such as strings is that Delphi needs to guarantee that no memory leaks occur. So there's always a hidden Try/Finally block in such methods that will "finalize" the managed variables and release any allocated heap space. That takes time to execute, even if there's no further "code" in the method.
  18. All the time. I am especially fond of classes that have only class methods. They basically act as namespaces.
  19. What exactly is a "local field" ? Do you mean a private field of a class (a member of an instantiated object, located on the heap) , or do you mean a local variable of a procedure or method (located on the stack) ?
  20. This makes the object unusable for multi-threading because it is unnecessarily stateful.
  21. Would that not potentially incur a cache miss, if the pointer points to a "remote" function?
  22. A.M. Hoornweg

    Ole DB (Ado) for MSSQL un-deprecated by Microsoft

    Could you please elaborate on that? Anything serious happening?
  23. A.M. Hoornweg

    Printing in a threaded program

    How do you detect if the printer is in use or not? You're accessing one stateful device that's effectively a singleton so the access has to be serialized. If you insist on using threads, you could write a dedicated printer thread.
  24. A.M. Hoornweg

    Initialization of returned managed types

    Thanks for mentioning this, downloading now...
  25. tDictionary<T> does manage the lifetime of refcounted objects (interfaces, strings, anonymous methods, ...). If it's in the dictionary, then that's proof that the object is still alive. Try achieving that with "tcomponent.tag!"... tObjectlist<T> can manage the lifetime of plain vanilla tObject and the user can specify whether he his wishes this behavior or not in the constructor. If yes, no dangling pointers, because the user is not supposed to free manually. Of course the user is not protected from doing silly stuff like still freeing the objects manually. That's life. Yes dictionaries add a few dozen KB to the executable. But hey, RTTI adds a megabyte or so of metadata and for many/most of us it's only dead weight. If there's one single place in the compiler chain where we should be given more control, it's there. Anyway, I myself have stopped using Tag for pointers to objects because dictionaries made my life much easier. I find myself often using strings as a key because I totally like it when the code tells what it's doing. Tag will only store a fixed pointer, but a dictionary will let me query if an object exists and where it is stored, without any ugly typecasting, in a compact and legible way. 🙂 procedure tform1.Button1click(sender:tobject); var callback:tReportShowEvent; begin if ReportDict.TryGet('CurrentReport',callback) then Callback(); end;