Unknown reason for AV inside a procedure [closed] - delphi

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I created an empty unit to store my public procedures and functions but I get access violation in the first line of a procedure, but this for the first time only I call this procedure, later calls work normally !!
The unit code:
unit myFunc;
interface
uses
Windows, Messages, SysUtils, System.UITypes, Variants, Classes, Graphics, Controls, Forms;
Procedure GSet(grid_form: TForm; app, operation: string);
implementation
Procedure GSet(grid_form: TForm; app, operation: string);
var
grd_idx: integer;
begin
if operation = 'save' then begin // Access violation in this line
if (grid_form.components[grd_idx] is TMyComponent) then
(grid_form.components[grd_idx] as TMyComponent).Storedata('c:\'+app);
end;
end;
Update:
I call this procedure from form create event like this
GridSettings(myform, 'cost', 'save');

From the code in the question, the most obvious mistake is that the variable grd_idx is not initialised. You must initialise variables before using them.
On top of that it is possible that you are passing an invalid object reference in the first parameter. We cannot tell from here. However, it is possible that you are passing a global variable that has not been initialised. It looks awfully like you should be passing Self rather than that global variable.
GridSettings(Self, 'cost', 'save');
Of course, I am assuming here that Self is what you intend to pass here. Since you did not supply very much code, we can only guess as to the details of your code.
You ask how to make the OnCreate event fire after all controls are created. Well, that is already the case. The OnCreate method is fired after the controls are created and their properties streamed in.
I would also comment that using strings to select discrete options is not a good idea. Use enumerated types for that.

Related

Ask about with Delphi source code [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 7 years ago.
Improve this question
I have a problem about Delphi source code.
Please help me explain it.
Detail problem as below:
I have two Delphi applications. They are two .dll files (it call App1 and App2).
App1 has a method as below:
procedure SetImage( objControl : Object; img: Pointer);
begin
objControl.Picture.Bitmap := img;
end;
In App2, I call above method of App1 as below to display image on report.
SetImage( objPreImgs, tempJPEG );
With objPreImgs is correct object and temJPEG is TJPEGImage object.
If I compile App1 and App2 with Delphi 7, there is not any problem.
If I compile App1 with Delphi 7 and App2 with Delphi 6, there is one problem (cannot display image on report).
I have not known root cause of above problem yet.
If you know, please explain for me.
p/s: App1 cannot compile with Delphi 6.
Despite the fact that both "apps" share a common memory area, each of them:
uses its own memory manager,
have their own VMT (virtual method table)
and the object model.
Thus, when you pass a pointer to an object in another "application", it considers its own and is looking for methods in own VMT. Naturally, D6 VMT differs from D7, which leads to AV, stack overflow and other errors.
So, you can`t pass objects and classes via dll | apps.
Returning to the task: you need to pass the contents of an image in a way that does not require the use of objects, for example - using iStream or SharedMemory. Also you can pass a handle to the image, because the handle is "global" value for both dll in the unified address space of the application. But...the first procedure (SetImage) is not necessary - this action must be performed in app2.
It cant compile because it's not the correct syntax
First of all objControl : Object should be objControl : TImage
img: Pointer should be img: TBitmap
objControl.Picture.Bitmap := img; shoud be objControl.Picture.Bitmap.Assign(img);
I belive you need a beginners book

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 document raised exceptions in Delphi? [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 5 years ago.
Improve this question
It happens to me quite often that I call a function Foo and want to know what exceptions this function might throw. In order to find out I then look into the implementation of Foo, but that is not enough. Foo might indeed call a function Bar that raises an exception.
Sometimes I even miss Java's checked exception handling.
So it is obivous to me that it is necessary to document the exceptions each function can throw: the question is: how? Are there any best practices on how to document exceptions? How do you handle this problem?
I think this covers some part of the problem you became aware of
Cleaner, more elegant and wrong
Cleaner, more elegant and harder to recognize
Most Delphi applications are VCL applications. They do not require a checked exception, because the main message loop has a try/except block catching everything.
It can be good practice to document which exceptions can be explicitly raised by your code though.
I'd use XMLDoc for that (there are various questions on XMLDoc her on SO, and here is some documentation from Embarcadero).
Note however that underlying code can also raise exceptions. Depending on the influence you have on libraries, you can or cannot assure those are always the same. A different thing is the OS: depending on where you run, you can get different exceptions.
--jeroen
We use Javadoc style comments for documentation. We extract the info and generate the output with some simple text scripts. We have used DelphiCodeToDoc, too.
Documenting exceptions, we have mandated to use the #throws tag.
this is looking great for documenting code - Documentation Insight from DevJet.net
I use XMLDoc comments. It's basically adding a specialized type of comment to your code in the interface section, just above the property or method declarations. Here's a nonsensical (of course) example. If you add similar style comments in your code, they'll pop up in Code Insight when you invoke it while writing code, just like the VCL's documentation does.
type
{$REGION 'TMyClass description'}
/// <summary>TMyClass is a descendent of TComponent
/// which performs some function.</summary>
{$ENDREGION}
TMyClass=class(TComponent)
private
// your private stuff
FSomeProp: Boolean;
procedure SetSomeProp(Value: Boolean);
protected
// your protected stuff
public
{$REGION 'TMyClass constructor'}
/// <summary> TMyClass constructor.</summary>
/// <remarks>Creates an instance of TMyClass.</remarks>
/// <param>Owner: TObject. The owner of the instance of TMyClass</param>
/// <exception>Raises EMyObjectFailedAlloc if the constructor dies
/// </exception>
{$ENDREGION}
constructor Create(Owner: TObject); override;
published
{$REGION 'TMyClass.Someprop'}
/// <summary>Someprop property</summary>
/// <remarks>Someprop is a Boolean property. When True, the
/// thingamajig automatically frobs the widget. Changing this
/// property also affects the behavior of SomeOtherProp.</remarks>
{$ENDREGION}
property Someprop: Boolean read FSomeProp write SetSomeProp;
end;
I prefer to wrap these XMLDoc comments in regions, so they can be collapsed out of the way unless I want to edit them. I've done so above; if you don't like them, remove the lines with {$REGION } and {$ENDREGION}
I use PasDoc for documenting almost all of my Delphi projects. It includes a "raises" tag which does what you seem to be asking for.
Regards
- turino

getting around circular references in Delphi [duplicate]

This question already has answers here:
Delphi Enterprise: how can I apply the Visitor Pattern without circular references?
(4 answers)
Closed 8 years ago.
Is there a way of getting around circular unit references in Delphi?
Maybe a newer version of delphi or some magic hack or something?
My delphi project has 100 000+ lines of code mostly based on singleton classes. I need to refactor this, but that would mean several months of "circular reference" hell :)
I've been maintaining close to a million lines of legacy code for the past 10 years so I understand your pain!
In the code that I maintain, when I've encountered circular uses, I frequently have found that they are caused by constants or type definitions in unit A that are needed by unit B. (Sometimes it's also a small bit of code (or even, global variables) in Unit A that is also needed by unit B.
In this situation (when I'm lucky!) I can carefully extract those parts of the code into a new unit C that contains the constants, type definitions, and shared code. Then units A and B use unit C.
I post the above with some hesitance because I'm not an expert on software design and realize there are many others here who are far more knowledgeable than I am. Hopefully, though, my experience will be of some use to you.
It seems you have quite serious code design issues. Besides many signs of such issues, one is the circular unit reference. But as you said: you cannot refactor all the code.
Move all what is possible to the implementation section. They are allowed to have circular references.
To simplify this task you can use 3rd party tools. I would recommend
Peganza Pascal Analyzer - it will suggest what you can move to the implementation section. And will give you many more hints to improve your code quality.
Use the implementation section uses whenever possible, and limit what's in the interface uses clause to what has to be visible in the interface declarations.
There is no "magic hack". Circular references would cause an endless loop for the compiler (unit A requires compiling unit B which requires compiling unit A which requires compiling unit B, etc.).
If you have a specific instance where you think you cannot avoid circular references, edit your post and provide the code; I'm sure someone here can help you figure out how to get it fixed.
There is many ways to avoid circular references.
Delegates.
Way too often, an object will execute some code that should be done in an event instead than being done by the object itself. Whether it is because the programmer working on the project was too short on time(aren't we always?), didn't have enough experience/knowledge or was just lazy, some code like this eventually end up in applications. Real world exemple : TCPSocket component that directly update some visual component on the application's MainForm instead of having the main form register a "OnTCPActivity" procedure on the component.
Abstract Classes/Interfaces. Using either of them allow to remove a direct dependance between many units. An abstract class or an interface can be declared alone in its own unit, limiting dependancies to a maximum. Exemple: Our application has a debug form. It has uses on pretty much the whole application as it displays information from various area of the application. Even worse, every form that allows to show the debug form will also also end up requiring all the units from the debug form. A better approach would be to have a debug form which is essentially empty, but that has the capacity to register "DebugFrames".
TDebugFrm.RegisterDebugFrame(Frame : TDebugFrame);
That way, the TDebugFrm has no dependancies of its own (Except than on the TDebugFrame class). Any and all unit that requires to show the debug form can do so without risking to add too many dependancies either.
There are many other exemple... I bet it could fill a book of its own. Designing a clean class hierarchy in a time efficient fashion is pretty hard to do and it comes with experience. Knowing the tools available to achieve it and how to use them is the 1st step to achieve it. But to answer your question... There is no 1-size-fit-all answer to your question, it's always to be taken on a case by case basis.
Similar Question: Delphi Enterprise: how can I apply the Visitor Pattern without circular references?
The solution presented by Uwe Raabe uses interfaces to resolve the circular dependency.
Modelmaker Code Explorer has a really nice wizard for listing all the uses, including cycles.
It requires that your project compiles.
I agree with the other posters that it is a design issue.
You should carefully look at your design, and remove unused units.
At DelphiLive'09, I did a session titled Smarter code with Databases and data aware controls which contains quite few tips on good design (not limited to DB apps).
--jeroen
I found a solution that doesn't need the use of Interfaces but may not resolve every issues of the circular reference.
I have two classes in two units: TMap and TTile.
TMap contains a map and display it using isometric tiles (TTile).
I wanted to have a pointer in TTile to point back on the map. Map is a class property of TTile.
Class Var FoMap: TObject;
Normaly, you will need to declare each corresponding unit in the other unit... and get the circular reference.
Here, how I get around it.
In TTile, I declare map to be a TObject and move Map unit in the Uses clause of the Implementation section.
That way I can use map but need to cast it each time to TMap to access its properties.
Can I do better? If I could use a getter function to type cast it. But I will need to move Uses Map in the Interface section.... So, back to square one.
In the Implementation section, I did declare a getter function that is not part of my class. A Simple function.
Implementation
Uses Map;
Function Map: TMap;
Begin
Result := TMap(TTile.Map);
End;
Cool, I thought. Now, every time I need to call a property of my Map, I just use Map.MyProperty.
Ouch! Did compile! :) Did not work the expected way. The compiler use the Map property of TTile and not my function.
So, I rename my function to aMap. But my Muse spoke to me. NOOOOO! Rename the Class Property to aMap... Now I can use Map the way I intented it.
Map.Size; This call my little function, who typecast aMap as TMap;
Patrick Forest
I gave a previous answer but after some thinking and scratching I found a better way to solve the circular reference problem. Here my first unit who need a pointer on an object TB define in unit B.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, b, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
FoB: TB;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
FoB := TB.Create(Self);
showmessage(FoB.owner.name);
end;
end.
Here the code of the Unit B where TB has a pointer on TForm1.
unit B;
interface
Uses
dialogs, Forms;
type
TForm1 = class(TForm);
TB = class
private
FaOwner: TForm1;
public
constructor Create(aOwner: TForm);
property owner: TForm1 read FaOwner;
end;
implementation
uses unit1;
Constructor TB.create(aOwner: TForm);
Begin
FaOwner := TForm1(aOwner);
FaOwner.Left := 500;
End;//Constructor
end.
And here why it compiles. First Unit B declare the use of Unit1 in the implementation section. Resolving immediately the circular reference unit between Unit1 et Unit B.
But to allow Delphi to compile, I need to give him something to chew on the declaration of FaOwner: TForm1. So, I add stub class name TForm1 who match the declaration of TForm1 in Unit1.
Next, when come the time to call the constructor, TForm1 is able to pass itself has the parameter. In the constructor code, I need to typecast the aOwner parameter to Unit1.TForm1. And voilĂ , FaOwner his set to point on my form.
Now, if the class TB need to use FaOwner internally, I don't need to typecast it every time
to Unit1.TForm1 because both declaration are the same. Note that you could set the declaration of to constructor to
Constructor TB.create(aOwner: TForm1);
but when TForm1 will call the constructor and pass itself has a parameter, you will need to typecast it has b.TForm1. Otherwise Delphi will throw an error telling that both TForm1 are not compatible. So each time you call the TB.constructor you will need to typecast to the appropriate TForm1. The first solution, using a common ancestor, his better. Write the typecast once and forget it.
After I posted it, I realized that I made a mistake telling that both TForm1 were identical. They are not Unit1.TForm1 has components and methods that are unknown to B.TForm1. Has long TB doesn't need to use them or just need to use the commonality given by TForm you're okay. If you need to call something particular to UNit1.TForm1 from TB, you will need to typecast it to Unit1.TForm1.
I try it and test it with Delphi 2010 and it compiled and worked.
Hope it will help and spare you some headache.

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