-
Content Count
1053 -
Joined
-
Last visited
-
Days Won
23
Everything posted by aehimself
-
While digging in the depths of a legacy application I was shocked to see that a binary data received through the network is stored and handled as a String. And it works. Imagine the following code: procedure TForm1.Button1Click(Sender: TObject); Var tb: TBytes; s: String; begin tb := TFile.ReadAllBytes('C:\temp\Project1.exe'); SetLength(s, Length(tb)); Move(tb[0], s[1], Length(tb)); // If CompareMem(@tb[0], @s[1], Length(tb)) Then ShowMessage('Contents are the same'); TFile.WriteAllText('C:\temp\project2.exe', s, TEncoding.Default); end; Fails. Produces the same amount of bytes, but it doesn't work. However, just by introducing a string casting: procedure TForm1.Button1Click(Sender: TObject); Var tb: TBytes; s: String; ans: AnsiString; begin tb := TFile.ReadAllBytes('C:\temp\Project1.exe'); SetLength(ans, Length(tb)); Move(tb[0], ans[1], Length(tb)); s := String(ans); TFile.WriteAllText('C:\temp\Project2.exe', s, TEncoding.Default); end; output executable is... well, executable. My bet is on some pointer magic Delphi is doing in the background, but can someone please explain WHY this works?!
-
Find exception location from MAP file?
aehimself replied to A.M. Hoornweg's topic in RTL and Delphi Object Pascal
I just want to make sure my logic is correct here. I built a really simple test, see .dpr and the generated .map file attached. I used this method to extract method addresses. Stack trace was as following: $0000000000429A84 $0000000000425327 $0000000000425C1B $000000000040A5C6 $000000000040A601 $0000000000429BE5 $0000000000429C0D $0000000000429C2D $0000000000429C82 $00007FFD09E97034 $00007FFD0A7A2651 Now, from each address I substracted image base ($400000) and $1000, which resulted the following relative addresses: $28A84 $24327 $24C1B $95C6 $9601 $28BE5 $28C0D $28C2D $28C82 $7FFD09A96034 $7FFD0A3A1651 In the map file "Address - Publics by name" section I looked for the address which is the closest but below each relative address. This gives me the method names. In the map file "Line numbers for xxx" section I searched for the exact relative address. This gives me the line numbers, if any. Based on the above approach my reconstructed stack trace is the following: StackTrace.GetExceptionStackInfo ( StackTrace:44 ) System.SysUtils.Exception.RaisingException ( ??? ) System.SysUtils.ExceptHandler ( System.SysUtils:23574 ) ??? ( System.pas:22018 ) ??? ( System.pas:22108 ) Project1.Three ( Project1:14 ) Project1.Two ( Project1:19 ) Project1.One ( Project1:24 ) Project1.Project1 ( ??? ) ??? ??? It resembles what went on, but I have some missing information which I was unable to find. I have two questions... is this the way to reconstruct the call stack from a map file? And if yes, how I can find the missing information? Project1.zip -
Listen to UDP in a TThread (Windows Service)
aehimself replied to Clément's topic in ICS - Internet Component Suite
TWSocket also implements this, you can call it by WSocket1.MessagePump. -
Love your competitor :-) ..... ?
aehimself replied to FranzB's topic in Project Planning and -Management
Thank. You. -
Love your competitor :-) ..... ?
aehimself replied to FranzB's topic in Project Planning and -Management
Wtf...? Btw I never experienced random crashes of my applications, not one since Windows 2000. I mean of course I did, but all of them was the fault of my code, not the OS silently attempting to kill it. And I would be REALLY surprised if it was true (especially now since Embarcadero / Idera has MS links if I'm not mistaken). -
We do have this combination at work. SCM is Git, client is written in Delphi, server is written in C#. Recently changed the process to use MSBuild to compile the Delphi project too. Works like a charm.
-
StackOverflow annual developer survey needs Delphi developers answering the survey
aehimself replied to FPiette's topic in General Help
They could use this information combined with the location to show "There are redhead / brunette / etc coders in your area" popups -
StackOverflow annual developer survey needs Delphi developers answering the survey
aehimself replied to FPiette's topic in General Help
You are completely right, I should have answered 哦□� That should have helped the devs to find out that there is nothing wrong with their input encoding 🙂 -
StackOverflow annual developer survey needs Delphi developers answering the survey
aehimself replied to FPiette's topic in General Help
Orly... -
Getting Exception stack trace in 2021
aehimself replied to Wagner Landgraf's topic in RTL and Delphi Object Pascal
I had ~2 releases with DebugEngine, then I switched back to MadExcept. It's stack traces are less messed up when packed with UPX. I'd personally prefer DebugEngine as it is not installing hooks (thus - not having the issues I mentioned) getting stack traces is it's main purpose. Performance wise - you won't feel a difference tbh. None of these tools will make your application less stable or significantly slower. -
Getting Exception stack trace in 2021
aehimself replied to Wagner Landgraf's topic in RTL and Delphi Object Pascal
I gave DebugEngine a try and it is very good. Sometimes it provides stack traces strange (method where exception happened, two inner methods of DebugEngine and then the real stack trace) but it's really easy to install and use. It is also unaffected by the two issues I have with MadExcept (TThread.FatalException and Exception.InnerException is rendered useless). It comes with a utility to attach the map (or it's own compressed smap) format to the .EXE itself, however the final executable is larger than with MadExcept (guess the .map compression is not that advanced in DebugEngine than in MadExcept). I don't have much experience with JclDebug... I tried it once, and I disliked every bit of it. Only to be able to see stack traces I had to include ~30 extra files in my project and the stack traces were not accurate.; so I gave up on it. If you can fit into the free usage conditions of MadExcept I'd say go with that. Otherwise, DebugEngine (or a license for MadExcept) would be my choice. P.s.: keep in mind that also MadExcept and DebugEngine is known to have stack issues if the .exe is packed with UPX. -
How to handle delphi exception elegantly with logging feature.
aehimself replied to HalfBlindCoder's topic in Algorithms, Data Structures and Class Design
This question is way too broad to be able to be answered correctly. In general, have Try..Except blocks. What you do inside the exception handler completely depends on the kind of application you are writing. If you don't want your application to crash / misbehave after an exception happened you have to make sure you "reset it to a default state". Roll back transactions, close datasets, free up objects, closing TCP connections, etc. You might want to make a note of it too for debugging purposes so write details to a log file and let your user know that something went south. It's also good to have stack traces so look into MadExcept / DebugEngine - both are really easy to install and can be used for free - with restrictions of course. -
What is the correct approach to "phone home"?
aehimself replied to Der schöne Günther's topic in Project Planning and -Management
Off: leaving my like because of hMailServer 🙂 -
What is the correct approach to "phone home"?
aehimself replied to Der schöne Günther's topic in Project Planning and -Management
#3. You might also want to look into WebDav. That way you simply can copy the file without any additional code (what you have to maintain) on the webserver. -
Binary data in String?
aehimself replied to aehimself's topic in Algorithms, Data Structures and Class Design
Thank you for the explanation, it all makes sense now. I don't really need workarounds; if this area will be touched it will be properly changed instead to use a hack-of-a-hack... Don't get me wrong - I know this should not be done because it won't work; this is why I was this surprised that it does in our case. The sole purpose of this topic was for me to understand why it does, when it should not 🙂 -
Binary data in String?
aehimself replied to aehimself's topic in Algorithms, Data Structures and Class Design
Update: wrong. #0s are not present. Var ss: TStringStream; s: TStream; tb: TBytes; begin ss := TStringStream.Create('Árvíztűrő tükörfúrógép'); Try s := ss; SetLength(tb, s.Size); s.Read(tb, Length(tb)); ShowMessage(TEncoding.Default.GetString(tb)); Finally FreeAndNil(ss); End; Lossy conversion as you mentioned, though. -
Binary data in String?
aehimself replied to aehimself's topic in Algorithms, Data Structures and Class Design
Not most likely, it does. Was Delphi 6 or 7, way before I joined the company. I know, this is why I was really surprised that it actually works like this. We are just lucky with our locale it seems 🙂 First one was only a demonstration; I knew it won't work. I found it strange that the output byte count is the same as the input (because of the double size as you pointed out) though. Guess I was lucky with the random choice of exe. So if I get it right... we read the binary data, doubling it's size as we pad each character with a #0 during AnsiString -> String conversion? The real code is creating a TStringStream out of this and passing it as a parameter of a method, which is expecting a stream. That method will access the contents with .Seek and .Read I suppose. I didn't test this, but am I safe to assume that this would include the extra #0s, causing the binary data to be corrupted? -
A long time ago I found this document, which shows the power of the .Filter property of DataSets. However it is Zeos-referenced I doubt that majority (or all) will not work on a regular dataset component. Feel free to take a look: ZeosLib - Browse /documentation at SourceForge.net and download zExpression.pdf.
-
Are you sure CONTAINING and STARTS are valid filter keywords? I'd try UPPER(ITEMNAME) LIKE ''' + SearchText + '''' instead.
-
Good quality Random number generator implementation
aehimself replied to Tommi Prami's topic in Algorithms, Data Structures and Class Design
Holy crap this is awesome! Imagine shrinking this to a hardware key 😄 -
Read-write protected, but read-only public property?
aehimself posted a topic in Algorithms, Data Structures and Class Design
Hello, I'm wondering how it is possible to achieve. Let's say I have an object: TMyObject = Class(TObject) strict private _status: String; strict protected Property Status: String Read _status Write _status; End; All fine, but how can I publish the same, Status property as public, read-only? In theory I could do (untested, only theory)... TMyObject2 = Class(TMyObject) strict private Function GetStatus: String; public Property Status: String Read GetStatus; End; Function TMyObject2.GetStatus: String; Begin Result := inherited Status; End; and from within TMyObject2's descendants I could say inherited Status := 'MyStatus'; to set the status. Now, can it be achieved that from within the thread I simply say Status := 'MyStatus' and everyone else can access this as a read-only property from the outside? -
Read-write protected, but read-only public property?
aehimself replied to aehimself's topic in Algorithms, Data Structures and Class Design
I'm aware of workarounds. I'm interested if the original one can be achieved. -
Read-write protected, but read-only public property?
aehimself replied to aehimself's topic in Algorithms, Data Structures and Class Design
If it would be, it would be a pretty weak attempt, wouldn't it? 😉 -
Read-write protected, but read-only public property?
aehimself replied to aehimself's topic in Algorithms, Data Structures and Class Design
This is exactly how I made my workaround. I'm just curious if it's possible to use the same name. -
Good quality Random number generator implementation
aehimself replied to Tommi Prami's topic in Algorithms, Data Structures and Class Design
program Project2; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; Const MAX_NUMBER = 1000; CYCLECOUNT = Integer.MaxValue; Var numbers: Array[0.. MAX_NUMBER - 1] Of Integer; a, min, max: Integer; begin Randomize; For a := Low(numbers) to High(numbers) Do numbers[a] := 0; For a := 1 To CYCLECOUNT Do Inc(numbers[Random(MAX_NUMBER)]); min := CYCLECOUNT; max := 0; For a := Low(numbers) To High(numbers) Do Begin If numbers[a] < min Then min := numbers[a] Else If numbers[a] > max Then max := numbers[a]; End; WriteLn('After ' + CYCLECOUNT.ToString + ' cycle(s), minimum amount of occurrences of the same number is ' + min.ToString + ', maximum is ' + max.ToString); ReadLn; end. After 2147483647 cycle(s), minimum amount of occurrences of the same number is 2144157, maximum is 2150811 That means, the luckiest random number was hit 6654 times more than the least lucky one (from more than 2 billion attempts!). Delphi's internal random number generator has a healthy dispersion. It's not perfect, but it is more than enough for average use.