Jump to content

Anders Melander

Members
  • Content Count

    2852
  • Joined

  • Last visited

  • Days Won

    156

Posts posted by Anders Melander


  1. 9 minutes ago, JIMSMITH said:

    Anyway I wonder how they handle exceptions so that other users continue to process without disruption..

    Supposedly each request is handled by a thread - Like in every other middleware.

     

    If your experience is that an exception in the request handling of the middle-tier blocks the whole server then there's either something seriously wrong with the middleware or the architecture of the middle-tier. The problem is probably that the main thread is somehow involved in the request handling.

     

    Not that it's related to your problem, but if you want middle-tier exceptions passed back to the client, as exceptions, you can look in the DataSnap source code to see how it's done.


  2. 31 minutes ago, Harbinger of Kru said:

    I am willing to reset my PC

    Impressive dedication 🙂 

     

    See if you can locate the Embarcadero Licence Manager somewhere on your system: LicenseManager.exe

    If you can run that, then you should be able to delete any prior license that might be in conflict with the new one.

    If everything else fails then you can try to delete all the license info manually. I believe it's in C:\ProgramData\Embarcadero\.licenses

    Note that this contains the license data for all Embarcadero products on your system so be careful.

     

    See also:

    https://docwiki.embarcadero.com/Support/en/Moving_from_Delphi_or_C%2B%2BBuilder_Community_Edition_to_another_edition

     


  3. 38 minutes ago, Kryvich said:

    I wrote about specifying short identifiers like Integer, PByteArray without a namespace inside a code section.

    Well, you said The Unit Scope Names setting helps abstract away implementation details which was what I have been trying to get an explanation of - but never mind.

     

    38 minutes ago, Kryvich said:

    Is there anyone here who writes System.Integer, Data.Win.ADODB.TADOQuery etc. in your code? And why?

    The example I gave with PByteArray is real; I have a core unit which declares TByteArray (of which PByteArray is a pointer to) as array[0..0] while SysUtils declares it as array[0..32767]. Since these two are ambiguous I have to scope my use of PByteArray when both units are used. No problem, SysUtils.PByteArray(some_pointer) doesn't obfuscate the code much. System.SysUtils.PByteArray(some_pointer) however is bit too verbose for my taste. FWIW, I just resolved it with a local type declaration: type PByteArray = System.SysUtils.PByteArray;

    • Like 1

  4. 2 hours ago, Kryvich said:

    I mean, you don't have to remember which system unit declares which type. You just write IntegerPByteArray instead of System.IntegerSystem.Sysutils.PByteArray and that's it!

    You still have to explicitly declare, in the uses clause, where PByteArray comes from - regardless of which form you use.

    And in the case of identifier ambiguity there is no difference in how it is resolved, regardless of fully qualified namespace or implicit namespace.

     

    So how does that explain your statement:

    5 hours ago, Kryvich said:

    Embarcadero can sometimes move system types and functions from one RTL unit to another. Should we care in which specific RTL module a particular system type is declared? The Unit Scope Names setting helps abstract away implementation details.

    If they move an identifier from one unit to another, you still have to update your uses clause and any explicit namespacing, since Delphi doesn't really have namespaces.  They can hide a move from Foo.SysUtils to Bar.SysUtils but not from System.SysUtils to System.FooUtils.

    I guess what you were referring to was a move from SysUtils to System.SysUtils.


  5. 35 minutes ago, EugeneK said:

    improves readability

    I'm not sure I agree on that.

     

    I've just been through a refactoring session where SysUtils was replaced with System.Sysutils which in turn made it necessary to resolve a series of type references as System.Sysutils.PByteArray instead of Sysutils.PByteArray due to a duplicate type declaration. That certainly didn't improve readability.

    • Like 1

  6. 3 hours ago, chkaufmann said:

    But when I look in WinApi.Windows.pas, then FindFirstFile maps to external symbol FindFirstFile (and not FindFirstFileW)

    You are looking at the function declaration.

    As Christian implied, for API functions that exist in both an Ansi and a Unicode version, you need to look at the import declaration:

    function FindFirstFile; external kernelbase name 'FindFirstFileW';

    and the declaration of TWin32FindData:

      TWin32FindData = TWin32FindDataW;

     

    I'm guessing it has been declared this way since the very first Unicode version of Delphi - as it should be. It's the same in C. In fact, the declarations were probably generated automatically from the C headers. I'm guessing the official Microsoft FindFirstFile documentation also mentions it.


  7. 1 hour ago, David Heffernan said:

    It's funny to see various people posting their own solutions when the original post contains a comprehensive implementation.... 

    Bike shedding

     

    5 hours ago, David Heffernan said:

    This code would be much better if each check of file header was done with same same code, against a signature

    For example like this:

    https://github.com/graphics32/graphics32/blob/b45d1108a8f57b66739731e952f81e2636c63abd/Source/GR32.ImageFormats.pas#L386

     

    Example of use:

    const
      FileSignaturePNG: AnsiString        = #$89#$50#$4e#$47#$0d#$0a#$1a#$0a;
      FileSignaturePNGMask: AnsiString    = #$ff#$ff#$ff#$ff#$ff#$ff#$ff#$ff;
    
    ...
    
    function TImageFormatAdapterPNG.CanLoadFromStream(AStream: TStream): boolean;
    begin
      Result := CheckFileSignature(AStream, FileSignaturePNG, FileSignaturePNGMask);
    end;

     

    • Haha 1

  8. 20 hours ago, Brandon Staggs said:

    Interesting that Bauer and Primoz take opposite sides.

    I can't see that they do.

     

    Here's the TLDR as I read it:

    Allen is saying that you shouldn't (mindless or not) use FreeAndNil to solve logic/design bugs and AFAICT nobody is disagreeing with that.

    Primoz and David are saying that they are using it to find stale reference bugs.

     

    Allen's suggestion to use a debug memory manager instead isn't valid because you can't do that on a production system, as Primoz also points out.

    • Like 1

  9. Just now, Brandon Staggs said:

    you will not know about the second FreeAndNil because it will succeed and move on, where a second call to .Free will instead cause a pointer error.

    Okay, now I understand what you meant.

     

    Yes, it's true that I'm trading the ability to catch one problem for another. However, the problem you are describing does not seem to be one that we are experiencing much if ever, so I'll take that trade.

     

    Regardless, we have made an active choice to use FreeAndNil this way. Not because we don't know any better but because we have a specific (recurring, I might add) problem that it helps us solve. I totally get the argument against just mindlessly using it CCP style but I can't really see how that applies to how we use it.

     

    I'd still like to know about these alternatives I should be using though...

     

    11 minutes ago, Brandon Staggs said:

    David asked what the harm in using FreeAndNil can be. That's what we are discussing. You're allowed to disagree, of course. But the point is to answer the questions about why FreeAndNil should be used for its intended purpose, rather than a debugging tool.

    Well, that's nice but no that's not what we are discussing. I gave an example of how and why we used it and you said that that usage had been "debunked".


  10. 11 minutes ago, Brandon Staggs said:

    A *LOT* can happen on a nilled object reference without creating an AV. 

    I have not claimed otherwise. It's not a magic "find all your bugs" tool. It's a "better than nothing" tool.

     

    Again, you are arguing against real world experience on actual code. I don't see the point.

     

    14 minutes ago, Brandon Staggs said:

    Understanding why it is designed that way should be enough to answer your own questions about why you should not be abusing FreeAndNil as a debugging tool. 

    I understand it and no, (roses are red, violets are blue) it does not answer my question and neither did you.

     

    16 minutes ago, Brandon Staggs said:

    There are purpose-built tools for catching use-after-free conditions.

    Such as?

    Debug memory managers are not suited for this use case; They can not be used in production code because of their overhead. FreeAndNil has practically no overhead.

     

    20 minutes ago, Brandon Staggs said:

    a side-affect of FreeAndNil which can only catch use-after-free SOMETIMES.

    Again, I never claimed otherwise. Sometimes is better better than never.

    If there was a better alternative I would happily use that but I'm not hearing any.

     

    22 minutes ago, Brandon Staggs said:

    In my own code I just make my intent clear by only using FreeAndNil when it is appropriate for the code

    That's fine. In our code we make our intent clear by documenting it: With comments in the code where we rely on the order of nil and free. With a section in our development guidelines and style guide about all the other cases; When, why, and how and when not to use it.


  11. 3 hours ago, Brandon Staggs said:

    This idea has already been debunked in this thread.

    Oh really? It appears to me that you are arguing a theoretical standpoint against the actual real world experience I have with finding stale object pointers using FreeAndNil.

     

    3 hours ago, Brandon Staggs said:

    It will only AV if that function somehow leads to instance memory being used.

    Yes, that's the point. Did anyone claim otherwise?

     

    3 hours ago, Brandon Staggs said:

    For example, you can easily call .Free on a nil object pointer, and it will succeed just fine

    It will succeed because it has been designed to do so. How is that relevant to FreeAndNil?

     

    3 hours ago, Brandon Staggs said:

    you may actually be hiding a logic error in your code by nilling the object before calling free a second time.

    What second time? What logic error? What are you even talking about?

     

    All this focus on free is pretty irrelevant to my use of FreeAndNil. I'm obviously not using it to guard against double frees because it doesn't do that.

    I'm using it to catch access though stale object pointers. End of story.

     

    I like to think that I actually know pretty well what I'm doing but I get the impression that you imagine I code by just throwing stuff against the wall to see what sticks.


  12. 4 hours ago, Uwe Raabe said:

    At least we've got some insights now.

    Yes. We now know Marco can read the help. Beyond that I don't know what we learned. Maybe that they don't have any compiler engineers at hand since the product manager had to do first level support and guess about the work required.

    The issue was filed as a New Feature but treated as a Bug report.

     

    Not impressed.

    • Like 1

  13. 4 minutes ago, Dalija Prasnikar said:

    For me it is about code intent. FreeAndNil implies reusable variables and more complex instance lifetime. Free implies the opposite.

    Instead of FreeAndNil implying a certain pattern I think it would be better to explicitly state, in a comment, when and why a certain behavior is expected.

     

    The projects I'm working on right now has something in the neighborhood of 200 calls to FreeAndNil in it. All except two are there to catch stale pointers; FreeAndNil gives us a nice AV that we can easily debug. Free would most likely give us a sporadic random error somewhere else.

     

    The two remaining cases are in a framework where we need a container var to be nilled before the object is destroyed. I won't go into why it's necessary; I'm sure you know the pattern. Anyway, for these two cases, the comments in the code clearly document why the FreeAndNil pattern is necessary.

     

    This is an old project and the introduction of FreeAndNil, where it makes sense of course, has helped us catch and eliminate countless bugs. Before I took over as the lead the code was littered with hundreds of empty try..except blocks simply because they had given up on trying to find the cause of the exceptions.

    • Like 2

  14. 26 minutes ago, Lajos Juhász said:

    It is not (yet) addressed in Delphi 12.2 it still defaults to 0 instead of 1.

    Don't expect it to be "fixed". The best you can hope for is that it is documented.

     

    The current behavior is consistent with class initialization; If you have the same field in a class and create a new instance, then the ordinal value of the field will be zero - as expected.


  15. Bummer.

    I've just checked both my desktop (which is a *ehem* 15 years old home build) and my laptop which is the top Lenovo X1 model, 2 years old, and neither of them support S0.

    This means that I unfortunately can't help debug the problem.

     

    If anyone else wants to have a go at it, the command to check for S0 support is powercfg /a.

    Note though that if Modern Standby isn't already enabled then it requires a complete OS reinstall to enable it. Yup, you read that right. Nice one, Microsoft.

    • Like 1

  16. 45 minutes ago, c0d3r said:

    there is no new PING records in the server database after exit from the standby

    You are looking at the symptoms at the end of a long chain of circumstances. You need to look at the other end, which supposedly (assuming WM_TIMER is the problem) is closer to the source of the problem.

     

    33 minutes ago, c0d3r said:

    I think the timer is dead completely (I was at least waiting for 5+ minutes to check).

    If standby killed WM_TIMER then millions of applications would break so I think it's very unlikely.

     

    The bug in PuTTY wasn't that the timer didn't fire but that they assumed that it would fire with a certain time interval and WM_TIMER is never guaranteed to do that.

     

    AFAIK WM_TIMER is a low priority message which is only synthesized when the message queue is polled and no higher priority messages are in the queue (or synthesized). I don't know your application but it could be that the queue is simply flooded with other stuff after resume from standby.

     

    So instead of assuming that WM_TIMER doesn't work I recommend that you simply verify with a simple application that does nothing but write a time stamp to a TMemo every time a 1 second TTimer fires.

    If that doesn't work then there's a problem with TTimer and we can start examining what that is.

    • Like 1
×