How Delphi objects work in code [closed] - delphi

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
I have been looking at system.pas
Delphi can call up to 65,000 memory blocks from windows
When Delphi makes an object dose it call a memory block for its data
And if so does the class some how load a register with a memory address for that memory block and an address for the methods too that is placed in another register.
Does any one know anything about this?
J Lex Dean.
With GetMem you call from windows a memory block that windows allocates up to 65,000 per process inside the 4 gig space. Depending on the fag depends on if the block is moved when resized with the data relocated in the resize or fixed and other issues.
Read about Windows or go to windows.pas and search on memory and call on your Delphi help
Thier is a lot of funny things with system.pas like1/ _ObjectProcess as if to add confustion to delphi programmers. Why do they not just put code in TObject. 2/ And how does code measure deliration size of an object.

Have a look at this excellent explanation about what's going on when Delphi creates new Class instances: The Rise and Fall of TObject from Hallvard Vassbotn
Although the original article appeared in 1998, most of it is still true for newer Delphi versions.
Here is the original article from The Delphi Magazine:The Delphi Magazine, July 1998

Where does your "65000 memory blocks" statistic comes from?
When a class instance is Created, the following class method is called before executing the Create method of the class (from _ClassCreate global function, which ensures that the instance is created only once, for all Create nested calls):
class function TObject.NewInstance: TObject;
Which calls GetMem to get memory from the heap, and then the following method:
class function TObject.InitInstance(Instance: Pointer): TObject;
This InitInstance method will:
Call FillChar() to put all the previously allocated memory to 0;
Initialize the Interface Table of the object.
The methods (i.e. not the interfaces) are defined in the class type itself, not during class instance creation.
There is no "register" containing what you say.
You have access to the object memory address by its self variable, or by trans-typing its variable to a pointer:
var O: TObject;
begin
O := TObject.Create;
writeln('O memory address is ',pointer(O));
O.Free;
end;
And before Delphi 2010 and its enhanced RTTI, you don't have access to all methods and fields of an object. Only published properties and methods are accessible to your code. But you must use RTTI. See TypInfo.pas unit.

Related

Delphi classes, shared memory, and varying DLL loading addresses

I'm working with an old and complex system that shares memory between dozens (sometimes hundreds) of Win32 processes. The code is mostly very old Pascal that has been ported to Delphi a few years ago.
(Almost) all of the code is in a single DLL, which all of the processes load. At the moment, we have forced a fixed loading address of that DLL. Image base is defined and ASLR is disabled in linker settings. Each process checks the DLL loading addresses at startup and the entire system refuses to work if the DLL cannot be loaded at the exact same address in all of the processes. This is of course a problematic solution. Sometimes customers have all sorts of 3rd party gadgets which affect the address space and prevents our product from having the address it wants for the DLL.
The reason for the fixed DLL loading address is below. I'm wondering if there is a way to work around this problem.
I've been trying to introduce object-oriented programming. The problem is, if I instantiate a Delphi class in the shared memory, that instance now seems to be dependent on the DLL loading address. For example, if another process tries to destroy that object, it will crash, unless the two processes happen to have the same DLL address. Delphi runtime seems to save function addresses in the object instance, assuming they will stay fixed for the lifetime of the object.
One possible solution might be to copy the DLL contents to the shared memory, then do some sort of magic trickery on DLL_PROCESS_ATTACH to make the process run that copy of the code instead of the loaded DLL address. The shared memory we have is always mapped at the same addresses. (Yes, this is also a problem sometimes but very rarely since the shared memory can be mapped at high (above 2 GB) addresses which are easily available.)
Or is there a way to tell Delphi compiler "please do not assume that the addresses of the functions related to this class are fixed"? I'm using Delphi 11.1.
I was able to figure out a a solution that seems to work well, so let me answer my own question.
The issue is that in order for dynamic dispatch to work, the object instance must be 'tagged' with type information. In the case of Delphi in Win32, this tag is in the first 32 bits of the object instance, and it is a memory address into the DLL where the the code of the class in question is.
If you shift this address to match the variable (process-specific) address of the DLL, the dynamically dispatched methods work fine. In order to do this, you need to compare this address to the loading address of the DLL (or any other reference address inside the DLL) and save the offset, when creating the object.
Then, before calling the object's methods in another process, "localize" the object by taking the actual address of the DLL, adding the offset, and writing this sum to the first 32 bits of the object.
Now you can use the object in any process, as long as you localize it first:
Obj.Localize;
Obj.Do_Something;
This can be neatly wrapped in a class.
Offset is simply a private 32-bit UInt32.
constructor Global_Object.Create;
begin
Self.Offset := PUInt32(Self)^ - Self.Reference_Address;
end;
procedure Global_Object.Localize;
begin
PUInt32(Self)^ := Self.Reference_Address + Self.Offset;
end;
destructor Global_Object.Destroy;
begin
inherited Destroy;
end;
function Global_Object.Reference_Address
: Cardinal;
begin
// Anything in the DLL can be used as a reference,
// such as the address of this function.
Result := Cardinal(#Global_Object.Reference_Address);
end;

Dynamic objects in delphi [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I know dynamic objects are objects created during run time. I have to make use of dynamic objects for a project, but not quite sure what to do. I'm not too sure what dynamic objects actually are except for the definition and for example once a button is clicked a panel is created, but this isn't exactly what is wanted from me. It is supposed to be more complex and meaningful.
What are other examples of dynamic objects and when or why would you use it?
Any instance of a class created at runtime in your code, and freed when you no longer need them. This happens all the time for classes that aren't visual components and can't just be dropped on a form.
Basic examples are things like TStringList for working with strings or text files, TStream descendants like TFileStream or TResourceStream, threads using TThread, generic lists such as TList<T>, and many other classes.
For instance, to work with a text file, an example of a dynamically created TStringList could be as follows:
var
SL: TStringList;
begin
SL := TStringList.Create;
try
SL.LoadFromFile('C:\Temp\MyFile.txt');
SL[0] := 'I changed this line.';
SL.SaveToFile('C:\Temp\MyFile.txt');
finally
SL.Free;
end;
end;
This sounds like a class project, and you don't seem to understand some of the terminology involved.
Just to generalize on this a little bit, in Delphi, instances of ANY class you define need to be created dynamically. This contrasts with records, which can be declared statically as variables as well as allocated dynamically.
In both cases (classes and records), when you create an instance dynamically, the memory for them is allocated from the heap, rather than the stack (where local vars are created). But the syntax is different in each case.
In Delphi, this contrasts sharply with C++, because C++ classes are basically structs (like Delphi records) with some embellishments, meaning that you can declare instances of classes in C++ as member variables where their memory is allocated on the stack in the same way you can declare instances of structs, as well as records in Pascal.
But this doesn't work in Delphi, even though the syntax looks the same. That's because in Delphi, the variables referring to classes are really pointers, like in C++, but they're automatically dereferenced, so they look syntactically as if they're just instances rather than a pointer-to-an-instance.
In Delphi, if you're working with a class, you MUST create it dynamically (by calling TMyObj.Create(...)). Thus, every class has a constructor associated with it; if you don't define one, the default TObject.Create constructor is called. (This is again different than in C++ where a default constructor will be created for you by the compiler for any class that needs one and it's not defined.)
I'll repeat this again so you're clear about it. Anything defined like THIS in Delphi:
type
Twhatever = class
is equivalent to this:
type
Twhatever = class( TObject )
and absolutely MUST be created dynamically in your code like this:
var
xyz : Twhatever; // xyz is really a pointer here! It's NOT an "instance"
begin
xyz := Twhatever.Create(); // you need to create an instance using the Create() method
try
// do some stuff
finally
xyz.Free;
end;
You cannot NOT use xyz without first creating an instance of it via it's .Create method.

How to define a procedure type that works for a local procedure? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I'm creating a request queue in a custom thread TMyThread and I'm having difficulties defining a procedure type which can be used for a subroutine. I have a record which represents the request, a corresponding record pointer, and a procedure type which is used in the record and uses the record pointer...
type
PRequest = ^TRequest;
TResponseProc = procedure(Sender: TMyThread; Request: PRequest);
TRequest = record
Request: String;
Proc: TResponseProc;
Response: String;
end;
The problem is, when I implement a subroutine named ResponseProc and try to assign ResponseProc to a TResponseProc, it doesn't work, and the IDE returns this error message:
[DCC Error] MyProject.dpr(42): E2094 Local procedure/function 'ResponseProc' assigned to procedure variable
How do I define this procedure type TResponse and use it with a subroutine?
The record and procedure declarations are fine. The error message indicates that you're using a local procedure, which is one that's defined inside the scope of another function. You cannot use pointers to such functions because they require extra work to call, which cannot be expressed in an ordinary function pointer. (The compiler disallows creating pointers to functions that a caller won't know how to use.)
The solution is to move your function outside whatever other function you defined it in. If that's hard to do because the inner function uses variables from the outer function, then you'll have to figure out some other way of getting their values to the other function, such as by passing them as parameters, perhaps making them additional members of that request record.
Another option is to use a procedure reference, and then define the local procedure as an anonymous procedure instead. It can access local variables, although only Delphi and C++ Builder will know how to invoke it, so it's not an option if you need external API compatibility.

Invalid pointer operation in TMonitor.Destroy

I'm currently working on porting an existing Delphi 5 application to Delphi 2010.
It's a multithreaded DLL (where the threads are spawned by Outlook) that loads into Outlook. When compiled through Delphi 2010, whenever I close a form I run into an "invalid pointer operation" inside TMonitor.Destroy... the one in system.pas, that is.
As this is an existing and kinda complex application, I have a lot of directions to look into, and the delphi help doesn't even document barely documents this particular TMonitor class to begin with (I traced it to some Allen Bauer posts with additional information) ... so I figured I'd first ask around if anyone had encountered this before or had any suggestions on what could cause this problem.
For the record: I am not using the TMonitor functionality explicitly in my code, we are talking a straight port of Delphi 5 code here.
Edit Callstack at the moment the problem occurs:
System.TMonitor.Destroy
System.TObject.Free
Forms.TCustomForm.CMRelease(???)
Controls.TControl.WndProc(???)
Controls.TWinControl.WndProc((45089, 0, 0, 0, 0, 0, 0, 0, 0, 0))
Forms.TCustomForm.WndProc(???)
Controls.TWinControl.MainWndProc(???)
Classes.StdWndProc(15992630,45089,0,0)
Forms.TApplication.ProcessMessage(???)
The pointer to the System.Monitor instance of each object is stored after all the data fields. If you write too much data to the last field of an object it could happen that you write a bogus value to the address of the monitor, which would most probably lead to a crash when the destructor of the object attempts to destroy the bogus monitor. You could check for this address being nil in the BeforeDestruction method of your forms, for a straight Delphi 5 port there shouldn't be any monitors assigned. Something like
procedure TForm1.BeforeDestruction;
var
MonitorPtr: PPMonitor;
begin
MonitorPtr := PPMonitor(Integer(Self) + InstanceSize - hfFieldSize + hfMonitorOffset);
Assert(MonitorPtr^ = nil);
inherited;
end;
If this is a problem in your original code you should be able to detect it in the Delphi 5 version of your DLL by using the FastMM4 memory manager with all checks activated. OTOH this could also be caused by the size increase of character data in Unicode builds, and in that case it would only manifest in DLL builds using Delphi 2009 or 2010. It would still be a good idea to use the latest FastMM4 with all checks.
Edit:
From your stack trace it looks like the monitor is indeed assigned. To find out why I would use a data breakpoint. I haven't been able to make them work with Delphi 2009, but you can do it easily with WinDbg.
In the OnCreate handler of your form put the following:
var
MonitorPtr: PPMonitor;
begin
MonitorPtr := PPMonitor(Integer(Self) + InstanceSize - hfFieldSize + hfMonitorOffset);
MessageDlg(Format('MonitorPtr: %p', [pointer(MonitorPtr)]), mtInformation,
[mbOK], 0);
DebugBreak;
// ...
Now load WinDbg and open and run the process that calls your DLL. When the form is created a message box will show you the address of the monitor instance. Write down the address, and click OK. The debugger will come up, and you set a breakpoint on write access to that pointer, like so:
ba w4 A32D00
replacing A32D00 with the correct address from the message box. Continue the execution, and the debugger should hit the breakpoint when the monitor gets assigned. Using the various debugger views (modules, threads, stack) you may get important information about the code that writes to that address.
An invalid pointer operation means your program attempted to free a pointer, but there was one of three things wrong with it:
It was allocated by some other memory manager.
It had already been freed once before.
It had never been allocated by anything.
It's unlikely that you'd have multiple memory managers allocating TMonitor records, so I think we can rule out the first possibility.
As for the second possibility, if there's a class in your program that either doesn't have a custom destructor or that doesn't free any memory in its destructor, then the first actual memory deallocation for that object could be in TObject, where it frees the object's monitor. If you have an instance of that class and you attempt to free it twice, that problem could appear in the form of an exception in TMonitor. Look for double-free errors in your program. The debugging options in FastMM can help you with that. Also, when you get that exception, use the call stack to find out how you got to TMonitor's destructor.
If the third possibility is the cause, then you have memory corruption. If you have code that makes assumptions about the size of an object, then that could be the cause. TObject is four bytes larger as of Delphi 2009. Always use the InstanceSize method to get an object's size; don't just add up the size of all its fields or use a magic number.
You say the threads are created by Outlook. Have you set the IsMultithread global variable? Your program normally sets it to True when it creates a thread, but if you're not the one creating threads, it will remain at its default False value, which affects whether the memory manager bothers to protects its global data structures during allocation and deallocation. Set it to True in your DPR file's main program block.
After a lot of digging it turns out I was doing a nice (read: horrifying, but it has been properly doing its job in our delphi 5 apps for ages)
PClass(TForm)^ := TMyOwnClass
somewhere deep down in the bowels of our application framework. Apparently Delphi 2010 has some class initialization to initialize the "monitor field" that now didn't happen, causing the RTL to try and "free the syncobject" upon form destruction because getFieldAddress returned a non-nil value. Ugh.
The reason why we were doing this hack in the first place was because I wanted to automatically change the createParams on all form instances, to achieve an iconless resizable form. I will open up a new question on how to do this without rtl-breaking hacks (and for now will simply add a nice shiny icon to the forms).
I will mark Mghie's suggestion as the answer, because it has provided me (and anyone reading this thread) with a very large amount of insight. Thanks everyone for contributing!
There are two TMonitor in Delphi:
System.TMonitor; which is a record, and is used for thread synchronization.
Forms.TMonitor; which is a class representing an attached monitor (display device).
System.TMonitor is added to Delphi since Delphi 2009; so if you are porting a code from Delphi 5, what your code was using was Forms.TMonitor, not System.TMonitor.
I think the class name is referenced without unit name in your code, and that is making the confusion.

What Design Patterns do you implement in common Delphi programming? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
What Design Patterns do you implement in common Delphi programming? What patterns are easier to adapt in Delphi programming? (Every language is excellent in different fields, so what patterns are likely to be very strong structures when using Delphi?)
I would be glad, if you could tell about some changes in design patterns for Delphi 2009 / 2010 (since those support generics, and RTTI in 2010).
There are many articles out there in the wild Internet, but they doesn't discuss the everyday usability and changes in patterns. (Most of them just discuss changes in language specifics, architecture).
Only a minority of the Delphi developers knows that every Delphi developer uses a Factory pattern (delphi.about.com has an example in "regular" Delphi), but then implemented using virtual Create constructors.
So: time to shed some light on that :-)
Virtual constructors are to classes like virtual methods are like object instances.
The whole idea of the factory pattern is that you decouple the logic that determines what kind (in this case "class") of thing (in this case "object instance") to create from the actual creation.
It works like this using virtual Create constructors:
TComponent has a virtual Create constructor so, which can be overridden by any descending class:
type
TComponent = class(TPersistent, ...)
constructor Create(AOwner: TComponent); virtual;
...
end;
For instance the TDirectoryListBox.Create constructor overrides it:
type
TDirectoryListBox = class(...)
constructor Create(AOwner: TComponent); override;
...
end;
You can store a class reference (the class analogy to an object instance reference) in a variable of type 'class type'. For component classes, there is a predefined type TComponentClass in the Classes unit:
type
TComponentClass = class of TComponent;
When you have a variable (or parameter) of type TComponentClass, you can do polymorphic construction, which is very very similar to the factory pattern:
var
ClassToCreate: TComponentClass;
...
procedure SomeMethodInSomeUnit;
begin
ClassToCreate := TButton;
end;
...
procedure AnotherMethodInAnotherUnit;
var
CreatedComponent: TComponent;
begin
CreatedComponent := ClassToCreate.Create(Application);
...
end;
The Delphi RTL uses this for instance here:
Result := TComponentClass(FindClass(ReadStr)).Create(nil);
and here:
// create another instance of this kind of grid
SubGrid := TCustomDBGrid(TComponentClass(Self.ClassType).Create(Self));
The first use in the Delphi RTL is how the whole creation process works of forms, datamodules, frames and components that are being read from a DFM file.
The form (datamodule/frame/...) classes actually have a (published) list of components that are on the form (datamodule/frame/...). That list includes for each component the instance name and the class reference.
When reading the DFM files, the Delphi RTL then:
finds about the components instance name,
uses that name to find the underlying class reference,
then uses the class reference to dynamically create the correct object
A regular Delphi developer usually never sees that happen, but without it, the whole Delphi RAD experience would not exist.
Allen Bauer (the Chief Scientist at Embarcadero), wrote a short blog article about this topic as well.
There is also a SO question about where virtual constructors are being used.
Let me know if that was enough light on the virtual Create constructor topic :-)
--jeroen
You can find an excellent article by Marco Cantu on the equivalence of GOF patterns and Delphi idioms. I remember attending his Borcon session on the subject, it was excellent.
One main idea to remember is that design patterns are needed to supplement shortcomings of the language/framework. And if you have a native idiom, you don't need to reinvent the wheel and implement the whole GOF shebang, just learn to recognize it and name it (as Jeroen did with his superb explanation on the Factory).
I use frequently following patterns:
Command
Visitor
Table Data Gateway
Observer
Adapter
Singleton (with many care!)
Abstract Factory
Factory Method
State
Dependency Injection in all of his form
Facade
Service Locator
Separated Interface
I frequently uses the following patterns:
Observer in MVC
Singlton
Template Method
State
Non-OOP programming (some call it Structured programming) is very common with Delphi programmers. It is very simple: You create a function that does something, and it is not related to a record/object-like data structure. Example: IntToStr()
Delphi does this very well, because encapsulation is delivered using interface/implementation sections, and because the resulting machine code is extremely efficient. When compiling, it also supports optimizations for that, for instance, if you have a typed constant in your interface section, and the program is fully compiled - if you then change the value of that constant, the unit is not recompiled, only the constant changes. This is not really necessary in a daily work, but it is an example of how Delphi works.
An ordinary Unit behaves like a singleton. You can't use OOP-techniques like inheritance and polymorfism though, but that might be a good thing :)
I generally think that Delphi makes it too easy to avoid sound oop design. That is nice for RAD, but you need to know which pitfalls to avoid if you want a flixible and maintainable code. Eg the public visibility for the components you add to the forms, the global Form1 variable of type TForm1 (instead of manually managed lifetime and a base class as type) and the lack of seperation between GUI and business logic. Just to mention some issues.

Resources