Re: String access error in class
- From: "Maarten Wiltink" <maarten@xxxxxxxxxxxxxxxxxx>
- Date: Fri, 28 Mar 2008 00:33:29 +0100
"Jamie" <jamie_ka1lpa_not_valid_after_ka1lpa_@xxxxxxxxxxx> wrote in message
news:3GVGj.8$EN.4@xxxxxxxxxxxxxxx
E Sterrett wrote:
I have included a stripped down version of a class I am using to store
configuration data in an ini file.
You might have stripped it down further to a single unoverloaded
constructor.
This works when I am using it from a simple console app. But when I
include it in a larger project, the constructor throws this error:
'Access violation at address 004050FC in module 'app.exe'. Write of
address 00000008'.
A null pointer. With a small offset...
This happens on the line: ComputerName:='test';
....at first glance consistent with the ComputerName field.
Obviously 00000008 is not a valid address. But I thought delphi handles
string address automatically.
Strings, yes. Objects, no.
What have I done wrong?
Probably calling a constructor on an object variable somewhere, instead of
on a class reference and storing the returned object in the variable.
Look for code that says 'Config.Create' instead of
'Config:=TConfig.Create'. If Config still happens to be nil, that would
cause these exact symptoms.
You don't show the code that creates the object. It seems somewhat
likely that you got it right in the console application, then messed
up the second time.
Lots of former C++ programmers make this mistake, through expecting
objects to be automatically allocated on the stack. In Delphi, object
variables are references, uninitialised, and the objects themselves are
_always_ created on the heap. And also always explicitly so, they are
never created automatically. Nor freed automatically, either.
unit Configuration;
interface
uses windows,inifiles,sysutils;
type
TConfig = Class(TObject)
public
FileName:string;
ComputerName:String;
As a rule, fields should be private, not public.
If you need outside access, make properties. (If you don't, make
properties anyway, but make them protected. Then never touch the
fields again.)
constructor Create(); overload;
constructor Create(FN:String); overload;
end;
var
IniFile : TIniFile;
implementation
constructor TConfig.Create(Fn:string)overload;
begin
IniFile := TIniFile.Create(Fn);
IniFile is a global variable. That can't be right. And it looks like
a form variable as created by the IDE, but for a class that isn't
apparent and may no longer exist.
ComputerName:='test';
filename:=fn;
end;
constructor TConfig.Create()overload;
begin
Create(Paramstr(0)+'.ini');
end;
end.
Try calling the inherited create first maybe?
That's a good habit but I don't think it makes a difference in this
case. (I still do think it _matters_. You should always call an
inherited constructor.)
Constructors can be called in either of two ways: on a class reference
or on an instance. The first case is handled by creating a new, blank
instance first through compiler magic, then calling the constructor
on the new instance as per the second case.
TObject.Create does nothing, so you don't lose any code by not
calling it. But that's just coincidence. Forgetting to call the
inherited constructor is dangerous and it is far better to always
call it as a matter of principle.
Groetjes,
Maarten Wiltink
.
- Follow-Ups:
- Re: String access error in class
- From: E Sterrett
- Re: String access error in class
- References:
- String access error in class
- From: E Sterrett
- Re: String access error in class
- From: Jamie
- String access error in class
- Prev by Date: String access error in class
- Next by Date: Re: String access error in class
- Previous by thread: Re: String access error in class
- Next by thread: Re: String access error in class
- Index(es):
Relevant Pages
|