Strange EAccessViolation which I cannot figure out...

delphi

    Next

  • 1. DCU file ownership
    I have a bit if a generic question as I want to gauge peoples opinions. We have an external supplier who previously wrote our applications and now supports them. I'm bringing the work in house gradually and taking the work off them which they are aware of. Our contract states that all of the work is owned by us and they have provided the vast majority of the files as agreed. However, there are a number of common functions etc... that they use and these have been provided as compiled units (.DCU). They won't release the .pas files unless we pay a licence and at which point, these will be split out (which is fine). The reason is that they consider these 'special materials' and part of their generic code for all clients. There is a clause in the contract, so I need to look closely at the implications. So, the question is do you consider DCU files to be sufficient for 'provided code'. We can re-build the vast majority, and probably re-use a lot of the source, but cannot check or change the code in these files. They cover things such as encryption functions that we use heavily. Having little experience of providing code in this way, I'd like to see what is generally thought of before forming my own opinions. Thanks Ryan
  • 2. BDS 2006
    I've got a full commercial (non-academic) license for BDS 2006 Pro that I wish to sell. I have posted it on eBay; it should be visible after 8pm PST today. Unopened, still in shrinkwrap.
  • 3. Lost Delphi 7 cd
    Hi all, I need help very badly. I lost my Delphi 7 cd (which came with Delphi 8 professional when I purchased that). I still have all of the registration information and disks for Delphi 8 except for the single Delphi 7 cd. I need that to continue my programming. Is there any place that would still have it for me? Borland said they no longer have it in any respect because it's so old. Any help would be greatly appreciated. Josh

Strange EAccessViolation which I cannot figure out...

Postby Ikke » Thu, 10 May 2007 01:45:47 GMT

Hi everybody,

While working on my first delphi project, I came across a strange 
EAccessViolation which I can't seem to put my finger on... 

There's a separate unit which contains a class TFileInfo, this class has 
a procedure to add doubles, and a function to return the doubles. Doubles 
are stored in a TObjectList. While filling the TObjectList, I can access 
the Count variable just fine - but as soon as I return the TObjectList, I 
can't access the variable anymore. Neither can I do something with the 
list.

Here's the code:
--- unit ---
unit FileInfo;

interface

uses Windows, SysUtils, ContNrs;

type
  TFileInfo = class
    private
      dbls : TObjectList;
    public
      procedure addDouble(var f : TFileInfo);
      function getDoubles() : TObjectList;
  end;

implementation

procedure TFileInfo.addDouble(var f : TFileInfo);
begin
  if (dbls = nil) then
    begin
      dbls := TObjectList.Create;
    end;

  dbls.Add(f);

  // this works perfectly!
  OutputDebugString(pchar('---' + IntToStr(dbls.Count) + '---'));
end;

function TFileInfo.getDoubles() : TObjectList;
begin
  // yet this does not... let alone being able to access dbls!
  OutputDebugString(pchar(dbls.Count));
  result := dbls;
end;

end.
--- end unit ---

The exact error I receive is:
"First chance exception at $7C4EA4E1. Exception class EAccessViolation 
with message 'Access violation at address 004609A2 in module 'DFR.exe'. 
Read of address 30306176'. Process DFR.exe (1244)"

I've already tried to compare dbls against nil, but it seems it is not 
nil, which is supposed to be like that.

Can anybody please shed some light on this one? I have no idea what's 
gone wrong, or what I could do to rectify this issue...

Thanks in advance!

Ikke

Re: Strange EAccessViolation which I cannot figure out...

Postby Tom de Neef » Thu, 10 May 2007 02:55:49 GMT

"Ikke" < XXXX@XXXXX.COM > schreef in bericht 


      constructor create;
      procedure free;
constructor TfileInfo.create;
begin
  inherited;
  dbls:=TobjectList.create;
end;

procedure TfileInfo.free;
begin
  dbls.free;
  inherited;
end;

//>  if (dbls = nil) then
//>    begin
//>      dbls := TObjectList.Create;
//>    end;

You do not show how the proc and function are called.
If you call GetDoubles before you call AddDoubles, you will have an AV since 
dbls is then not yet assigned. The OutputDebugString call will then cause 
the error.

In general, it is a good idea to define a Create constructor where you 
create all the contained objects. The destructor will call FREE; that's the 
place where you can destroy them again. I have added them in your code (and 
removed the 'if dbls=NIL' (NB: you trust it will be set to NIL upon 
creation. Maybe that's the case, but better not depend on such beliefs.).
Tell us if you still get the error.
Tom



Re: Strange EAccessViolation which I cannot figure out...

Postby Henry Bartlett » Thu, 10 May 2007 07:59:34 GMT

"Ikke" < XXXX@XXXXX.COM > wrote

Typecasting an integer as a pchar?

Try
  OutputDebugString(IntToStr(dbls.Count));




has
Doubles
access
TObjectList, I
the
EAccessViolation
'DFR.exe'.
not
what's



Re: Strange EAccessViolation which I cannot figure out...

Postby Rob Kennedy » Thu, 10 May 2007 08:42:29 GMT



The lazy initialization of dbls is fine, as long as it's lazily 
initialized everywhere. At first glance, it would seem as though the 
access violation is coming from checking the Count property of an 
uninitialized dbls field in GetDoubles. But that's not the case. The 
indication of that is the address being read, $30306176. If dbls were 
uninitialized, the address would be $00000000, or something very close 
to it.

My guess is that the variable being used to invoke the GetDoubles method 
is not initialized.


You've got it backward. The non-virtual Free method calls the 
destructor. Override the destructor named Destroy.


Actually, it's defined by the language that all fields will be 
all-bits-zero when the constructor starts running. It's required to be 
that way because of how the destructor might get called before the 
constructor finishes running.

-- 
Rob

Re: Strange EAccessViolation which I cannot figure out...

Postby Jamie » Thu, 10 May 2007 09:13:17 GMT

kke wrote:

#1.
You need a constructor, never assume that an object in a class
is always NILL just because you know you haven't created it yet.
Testing for NIL on an object pointer to check for verification of
a valid or not yet created object is not a good thing, how ever, it
does work ok if you design your code such that if for example, some
where in your code you are freeing and setting it to NIL to then later
on test for this condition to insure it is valid before using it...
The proper way is to always create it in the constructor or, Set it
to NIL so that proper flow can be had.

#2.
In your OutputDebugString(pchar(dbls.count)); is incorrect use of.

The dbls.counts yields a integer type, you have implied with a
type cast around this returned value as a pointer to a pchar string.
All this is going to do is generate a pointer to a memory location
address if which value, is the "COUNT" return "Number of items"
for example, if you have 6 items in the list, this will generate an
address of 6. this is most definitely out of your address space..
I think what you meant to do is this.
OutputDebugString(pchar(IntTostr(dbls.count)));

The INtTostr(...) generates a Delphi long string.,These types of
strings are referenced via a pointer. so the return value is a pointer
to the start of the first character of a delphi string.
Type casting the Pchar around it makes the DebugString function happy
into thinking it's looking at it's type of string..
etc...


--
"I'm never wrong, once i thought i was, but was mistaken"
Real Programmers Do things like this.
http://webpages.charter.net/jamie_5


Re: Strange EAccessViolation which I cannot figure out...

Postby Ikke » Thu, 10 May 2007 09:38:50 GMT

"Tom de Neef" < XXXX@XXXXX.COM > wrote in



<snip>
<snip>

Thanks to all who have replied - I can't try your suggestions/solutions 
right now, I'll try them in the morning.

One thing I'd quickly like to add, though, is that AddDoubles is indeed 
called prior to calling GetDoubles. Otherwise, I could indeed imagine an 
error popping up.

Thanks, and I'll reply tomorrow with the results!

Ikke

Re: Strange EAccessViolation which I cannot figure out...

Postby Rob Kennedy » Thu, 10 May 2007 10:46:59 GMT



That's a perfectly safe assumption. Constructors are documented to 
always set their objects' fields to zero, nil, empty, or unassigned 
(depending on each field's type). In fact, the documentation says "there 
is no need to initialize fields in a constructor implementation except 
to nonzero or nonempty values."


Aha, yes, that's the real problem.

-- 
Rob

Re: Strange EAccessViolation which I cannot figure out...

Postby Jamie » Thu, 10 May 2007 11:16:30 GMT





Sorry, you don't get it. If you don't set it to some fixed value at
start up, then in your code as you were using, you were testing for
the creation of the object just by testing for a NIL>
   In this case, you must either create the object of make sure you
clear the field to NIL>
   Regardless of what it saids in the help, I can tell you by experience
that you should not assume the class to Nil your fields for you 
automatically in the constructor.
   When memory is allocated, Delphi likes to zero it out, in this case
it will work how ever, if memory has been used already and it's still
in delphi's heap, it just simply gives you the memory. this means, what
ever was there before you get.

   The last time I knew, Delphi uses the option from the API to get a
zeroed chunk of memory..
   To speed things up, normally memory is not wiped while delphi has it
in it's own heap.


-- 
"I'm never wrong, once i thought i was, but was mistaken"
Real Programmers Do things like this.
 http://www.**--****.com/ 


Re: Strange EAccessViolation which I cannot figure out...

Postby Hans-Peter Diettrich » Thu, 10 May 2007 14:12:52 GMT




The Address 30306176 looks much more like 4 characters, than like a 
valid pointer.

DoDi

Re: Strange EAccessViolation which I cannot figure out...

Postby Maarten Wiltink » Thu, 10 May 2007 17:38:11 GMT







[...]

But that only applies during object _creation_. Admittedly it is an
obscure, marginal, little-known and little-used border case, but it
_is_ documented that constructors can be called on existing objects.
In fact, that is what happens during object construction: a new instance
is allocated and zeroed (in one step), and the constructor method called
on the new instance. You can call a constructor as a class method, but
Self will be the instance... won't it?

Groetjes,
Maarten Wiltink



Re: Strange EAccessViolation which I cannot figure out...

Postby Ikke » Thu, 10 May 2007 18:56:08 GMT

Tom de Neef" < XXXX@XXXXX.COM > wrote in
news:4640b9a6$0$331$ XXXX@XXXXX.COM :

Hi Tom,

I've made some changes to the code, but the error still remains. I'll
document below what I have changed.


---
constructor TFileInfo.Create(const fname : String;
const fsize : Int64);
begin
inherited;
self.fname := fname;
self.fsize := fsize;
dbls := nil;
end;
---

Never mind the other variables, I left them out in the previous post. Two
problems with this constructor, however:

1. If I add inherited, I no longer can compile this. The error I receive
is 'E2008 - Incompatible types'.

2. Instead of directly creating a new TObjectList, I have chosen to
initialise dbls to nil. Am I correct in assuming that an empty
TObjectList takes up memory space? If so, then I'd prefer the nil
approach, because there will be a lot of TFileInfo objects, yet only a
few will have the need for this dbls TObjectList.


Since I'm not sure whether or not dbls is used, and is or isn't nil, I've
changed this to:

---
procedure TFileInfo.free;
begin
if not (dbls = nil) then
begin
dbls.free;
end;
inherited;
end;
---


This part remains as it was, no changes needed...


I've used ShowMessage to be notified what's going on here. Here are the
changes:
---
function TFileInfo.getDoubles() : TObjectList;
begin
if (dbls = nil) then
begin
ShowMessage('Dbls is nil');
end
else
begin
ShowMessage(IntToStr(dbls.Count));
end;
result := dbls;
end;
---

Also, I added the IntToStr, as you have suggested (this was indeed a
mistake).

The message 'Dbls is nil' does not pop up (as expected with my testcase),
but I still get an error when the else part is executed. If I break the
program, the line indicated is indeed the ShowMessage in this else part.

The error I receive is:
"First chance exception at $7C4EA4E1. Exception class EAccessViolation
with message 'Access violation at address 00460A19 in module 'DFR.exe'.
Read of address 706A2E39'. Process DFR.exe (1408)"


Yesterday I've already replied very briefly to this, but in short I can
verify that AddDoubles gets called prior to the GetDoubles call.

The fact that the 'else' part is executed in GetDoubles verifies this...


Yes, I still get the error... And alas, I still can't figure out why :(

Thanks for the good advice, I'll make sure to add decent
constructors/destructors in future.

Ikke

Re: Strange EAccessViolation which I cannot figure out...

Postby Ikke » Thu, 10 May 2007 18:59:40 GMT

Jamie < XXXX@XXXXX.COM > wrote in



<snip>

Thanks for the advice - I've already replied to Tom with the necessary 
changes, and I've indeed added constructor/destructor code.

Am I correct in assuming that a newly created, empty TObjectList still 
takes up memory? If so, then I prefer to set the TObjectList to nil, 
rather than creating a new one.
 

Indeed - an oversight on my part. In the AddDoubles procedure I had it 
the right way round. Thanks for pointing this out!


The good news is that I've changed the call to IntToStr(dbls.count), the 
bad news is that I still get the error :(

Thanks,

Ikke


Re: Strange EAccessViolation which I cannot figure out...

Postby Ikke » Thu, 10 May 2007 19:00:35 GMT


@mid.individual.net:




Thanks for the information - however, I'm rather new at Delphi. Would you 
care to elaborate a little? I'm afraid that I can't seem to figure out a 
solution from this advice...

Thanks,

Ikke

Re: Strange EAccessViolation which I cannot figure out...

Postby Ikke » Thu, 10 May 2007 20:14:19 GMT

Ikke < XXXX@XXXXX.COM > wrote in



<snip>
<snip>

Never mind this one - I figured out that I need to call "Inherited 
Create;" .

Ikke

Re: Strange EAccessViolation which I cannot figure out...

Postby Hans-Peter Diettrich » Thu, 10 May 2007 23:31:33 GMT




I see ;-)

Something seems to be wrong with your code. Either somebody overwrites 
the container object, or the object is destroyed for some reason, making 
the reference to dbls s{*filter*}and freeing the memory for further reuse.

DoDi

Similar Threads:

1.Strange EAccessViolation which I cannot figure out... - SOLVED!!

Ikke < XXXX@XXXXX.COM > wrote in news:Xns992B8700A7019ikkehierbe@
195.130.132.70:

> Ikke < XXXX@XXXXX.COM > wrote in
> news: XXXX@XXXXX.COM : 
> 
> <snip>
>> 1. If I add inherited, I no longer can compile this. The error I
>> receive is 'E2008 - Incompatible types'. 
> <snip>
> 
> Never mind this one - I figured out that I need to call "Inherited 
> Create;" .

... and after hours of searching and banging my head against the wall, I 
finally was able to find the error.

As in most cases, NEVER assume you know exactly where the error is hidden 
in your source code when you're learning a new language.

Removing line after line of code, I came across the following in the 
event handler of the listbox that starts all the action. There's a line 
in there which reads:
---
f := TFileInfo(TListBox(Sender).Items[TListBox(Sender).ItemIndex]);
---
... with f being a TFileInfo variable. Now if only I had thought of the 
fact that listbox.Items holds TStrings instead of TFileInfo objects, I 
would have found the error a lot sooner. Damn Difficult to Debug Delphi 
I'd Dare say :)

Anyway, a big thanks to everyone who helped me!!

Ikke

2.Cannot connect to MySQL 5 with D2007 (cannot find dbxmys30)

Hi all

Delphi2007 Update 1
TSQLConnection (dbExpress4) set to the mySQL test database on localhost

On the SQLConnection.Open (before login) I get 'cannot load 
dbxmys30.dll'. It is in c:\program files\codegear\rad studio\5.0\bin 
(together with dbxmysA30.dll) and that dir is the first one in my PATH.

Any ideas?

[MySQL] section in dbxdrivers.ini:
DriverUnit=DBXDynalink
DriverPackageLoader=TDBXDynalinkDriverLoader
DriverPackage=DBXCommonDriver110.bpl
DriverAssemblyLoader=Borland.Data.TDBXDynalinkDriverLoader
DriverAssembly=Borland.Data.DbxCommonDriver,Version=
11.0.5000.0,Culture=neutral,PublicKeyToken=a91a7c5705831a4f

GetDriverFunc=getSQLDriverMYSQL
LibraryName=dbxmys30.dll
VendorLib=libmysql.dll
HostName=ServerName
Database=DBNAME
User_Name=user
Password=password
BlobSize=-1
ErrorResourceFile=
LocaleCode=0000
Compressed=False
Encrypted=False

No [mySQLConnection] entry in dbxconnections.ini

I traced the Open statement into the LoadDriverLibrary procedure.
Finally, way deep in 
function TDBXDynalinkDriverCommonLoader.Load(DriverDef: TDBXDriverDef): 
TDBXDriver;
the call to FMethodTable.FDBXLoader_GetDriver fails
What that code is doing I have no idea ;-)


Thanks in advance
Jan

3.Solved: Cannot connect to MySQL 5 with D2007 (cannot find dbxmys30)

4.Can't figure out how to pass a status message

This is a very basic programming thing but I guess I'm too
boneheaded to understand what to do.

Say that I have a TMemo, which is part of the main form (fMain).
It is there to display status messages.  How are the other
units supposed to pass a string to this TMemo.Add()?  The
only way I can think of is to put fMain in uses and call
it that way, but that's a crude solution.

Another idea is to make a shared Global unit and put a flag
in there, but this seems useless as there would be nothing
in fMain monitoring the flag until the subunit is done.

What are you supposed to do in this all-too-common situation?

~ Arthur

5.IDE sales figures

< XXXX@XXXXX.COM > wrote:

> The latest quarter's figures document a marked drop in revenues from
> the IDE division.
> "Revenue from its IDE products accounted for just 7% of total revenue
> in the third quarter of 2005, down from 15% in the same quarter a year
> earlier


Though that's probably the right interpretation, it's not the only one
possible from the statement given. If other revenues have risen, actual
revenue from IDE could have stayed the same (or even grown) while
representing a smaller percentage of overall revenue.

6. Delphi Job Market --personal observations: You get that inflated figure by

7. I think I figured this out...

8. Borland's Sales Figures ?



Return to delphi

 

Who is online

Users browsing this forum: No registered users and 9 guest