dormky
Members-
Content Count
114 -
Joined
-
Last visited
Everything posted by dormky
-
Every call prints "Thread ID start" and "Thread ID Exit" to the debug log.
-
How can I force a record to be allocated on the heap ?
dormky posted a topic in Algorithms, Data Structures and Class Design
I have a very, very large record that may cause memory issues for the stack if I use multiples instances of it in a procedure. I'd like to force delphi to allocate it on the heap so this doesn't happen. I need it to stay a record, it can't be a class. I have no problem with doing a bit of manual work in the procedure to get this, it doesn't have to be something baked in the framework and invisible to me as a dev. I'm sure this is possible in a simple way, I just can't find it through Google... Thanks ! -
How can I force a record to be allocated on the heap ?
dormky replied to dormky's topic in Algorithms, Data Structures and Class Design
Believe me I would love to move away from this pattern, but unfortunately we have decades-old data stored like this, with the whole rest of the program built around it. It's too late ; the only thing I can do now is make it as safe and as readable as possible for future generations, lol. -
TBloodyTColor1 = record aVar: smallint; aColor: TColor; end; TBloodyTColor2 = record aVar: smallint; aColor: TColor; aVar2: smallint; end; TBloodyTColor3 = record aVar: smallint; aVar2: smallint; aVar3: smallint; end; The results of "sizeof" for these 3 records are : TBloodyTColor1 : 8 TBloodyTColor2 : 12 TBloodyTColor3 : 6 The size of a TColor is 4 bytes, a smallint is 2 bytes. TBloodyTColor1 & 3 should take the same amount of memory, yet when using TColor 2 bytes are added. I believed this was for memory alignment purposes, but we can see that's not the case by looking at TBloodyTColor2, where 4 bytes are added (if I had to assume, they're probably 2 bytes before & after the TColor). This is incredibly annoying. It's basically impossible to predict how much space a record is going to take ! Looking at the definition of TColor, TColor = -$7FFFFFFF-1..$7FFFFFFF; indicates that the 7 here might be at fault ? Just looking for some insight on the subject, because this makes static analysis incredibly difficult for really no good reason...
-
TColor breaks memory layout
dormky replied to dormky's topic in Algorithms, Data Structures and Class Design
Unfortunately, no. Most of said records are just wrapping underlying anonymous arrays and records, and there's no RTTI generated for those (I need to get the actual name of the field so a human can read the comparison). A field like "array [0..1] of record X, Y: smallint; end;" doesn't have RTTI, and there's a lot of those. And for your entertainment, things are actually worse than this because anytime one of these arrays needs to be grown for a change in the program, we need to keep the old version of the record so we can read the old file, and a new one with the change. And all the fields need to be manually copied over, there's tens of thousands of lines of "current.field := V22.field" :') So yeah. I don't know who went with this model of configuration storage, but if I get my hands on them they're in trouble, to say the least. Edit : I could take out the anonymous stuff and declare it properly, but that would make an even bigger mess of things, add a lot more versioning like shown above, etc... All to be able to compare the god damned configs. So I want to evade doing that if possible, such a big number of changes would have no chance of me not making a mistake somewhere in my copy-pasting, and of course we have 0 tests. -
TColor breaks memory layout
dormky replied to dormky's topic in Algorithms, Data Structures and Class Design
Ah, thank you for the explanation and link, this is the info I was looking for ! @David Heffernan I'm looking into this because we have config files that are just memory dumps of records. I need to be able to meaningfully compare and manipulate those files. There is A LOT of them and doing so manually would be hopeless. -
How can I force a record to be allocated on the heap ?
dormky replied to dormky's topic in Algorithms, Data Structures and Class Design
@Alexander Sviridenkov Perfect, thank you very much ! -
How can I force a record to be allocated on the heap ?
dormky replied to dormky's topic in Algorithms, Data Structures and Class Design
That does simple to be the simple thing I was looking for, thanks ๐ How do I free this though ? -
How do I disable code completion ? It keeps giving me unit names, which is possibly the worse thing it could ever propose. I'm on Dlephi 10.3 and everything is already disabled, but the autocompletion still happens. Thanks !
-
Nevermind, just discovered that the autocompletion box had small buttons next to it and one of those is the settings for code completion.
-
How do I get a Pointer to a generic type ?
dormky posted a topic in Algorithms, Data Structures and Class Design
I'm trying to use TRttiField.SetValue with a generic type. TTestClass = class(TObject) testValue: Integer; end; function testProc<T>() : TArray<T>; // // Code to get the relevant field... // field.SetValue(Result[i], TValue.From<Integer>(47)); // Fails : E2010 Incompatible types: 'Pointer' and 'T' end; If I try to make a PByte(Result) myself, this also fails with an incompatible typecast. All a want is the address of my field so I can write a value there. Thanks ! Edit : Okay, found an horrendous solution : procedure makeCopy(var dest; value: Variant; field: TRttiField); begin field.SetValue(Pointer(dest), TValue.FromVariant(value)); end; This works for my simple field, probably won't for more complex stuff. You end up with an additional function call for every SetValue just to get around the compiler, but alas... -
How do I get a Pointer to a generic type ?
dormky replied to dormky's topic in Algorithms, Data Structures and Class Design
That's totally correct, but the fact that I can't grab a Pointer directly but there's a simple workaround shows that this is a (probably willful) limitation of the compiler. -
I have some code doing imports and updating the UI as it goes. When running with the debugger attached, everything goes fine. But running the exe itself (the exact same exe that was just compiled for the debugger run), the UI freezes. What's weird is that it only starts doing this after a few seconds, and not in the same place everytime either. What's going on here ? Has anyone encountered this before ? I can see the logs as the exe runs (with its UI frozen), so I know the code is still working fine. When I say "frozen", I mean that Windows whites it out and if you click on it, it will say that the program isn't answering.
-
The main thread is not frozen, the data is still being imported. It's just the UI that freezes after a few seconds. If the lack of call to Application.ProcessMessages() was at fault, the freeze would be immediate, but it's not, I can see rows getting added in the UI... until I can't because of the freeze. @Kas Ob.It's not done in a background thread. I would have mentioned it if it was. Same thing with the running time, it's the same in both instances.
-
Application.ProcessMessages() does not apply as a solution here. As I said, the freezing occurs after a few seconds ; before then the UI updates perfectly fine. So the application does process the messages, it's just that for some reason it stops after a while. Generally after 5-8sec.
-
I have calculations that need to be executed when a window is opened, but those calculations take a bunch of time. I'd like to run them after FormShow, so that the window is shown during the calculations. However, looking at the callsite of TCustomForm.DoShow, I don't see any event getting triggered after the show. So how can I do this ? The problem with FormActivate is that it's called a bunch of times, and having a flag for this seems like a hacky way to do something the framework should have a feature for. Thanks ๐
-
I consider it a "hacky way" of doing things because it pulls up state into a more global context, despite said state being single-use. That's a red flag to me, unless you are implementing this at framework level. And I consider being able to say "execute this after you're done drawing" to be a very basic framework feature.
-
All of these answers are exactly the kind of hack I'd hoped to avoid... Oh well.
-
I'd like to have my code formatted like this. I've seen it in multiple places on the internet but can't figure out how to get the right parameters. if condition then begin code; end else begin more code; end; if condition then begin code; end else if otherCondition then begin more code; end; I've tried using GE and the default RAD Studio formatter.
-
@Lajos Juhรกsz I am on Delphi Rio. The error is "Expected end but received var".
-
@haentschmanThe style guide mentions : // correct begin for var I: Integer := 1 to 10 do But I can't declare a var like this. What's the compiler setting to allow that ?
-
I agree with the fact that it's not 100% consistent. That's because having end else begin Is not that useful. 3 keywords each on one line is really wasteful.
-
I have a StringGrid where results get added every second. However, doing StringGrid.RowCount := StringGrid.RowCount + 1; Sets the scroll position back to the top. How do I prevent this ? It leads to horrendous jank in the UI because I need to set the scroll back to the bottom afterwards, leading to the scrollbar (and grid) jumping up and down every second. I'm on Delphi 10.3. Thanks !
-
@Stano Yes, but that would just hide the underlying problem ๐. Still, always a good idea to use BeginUpdate & EndUpdate to make UI changes ๐ @Pat Foley I've never seen an AddRow or equivalent function for StringGrid in Vcl. Plus, "doing it for me" wouldn't actually stop the problem from occuring.
-
So this code yields the best result, but requires that the last row keeps getting selected. The problem is that SetRowCount calls ChangeSize, which for some godforsaken makes sure that the anchor (ie, the top left) position is the same as the currently selected row. This means that on the next draw, your grid will "snap" to that currently selected row. This is obviously a completely idiotic implementation, but alas these are the joys of proprietary software. For the code I'm talking about, see Vcl.Grids's TCustomGrid.ChangeSize. Changing the size of something should never change its internal state(especially in such a massive way), but I guess programming standards were somewhat different in the days when this was written. Nice to see we're evolving at least ๐ StringGrid.RowCount := StringGrid.RowCount + 1; StringGrid.TopRow := StringGrid.RowCount - StringGrid.VisibleRowCount; StringGrid.Row := StringGrid.RowCount - 1; Embarcadero issue number : RSP-42421