GPF upon setting a property with {$LONGSTRINGS ON}

I don't understand why I would get a
GPF upon running this program with {$LONGSTRINGS ON} and not with
{$LONGSTRINGS OFF}.  The program doesn't do anything spectacular so I
don't see why it generates an EAccessViolation.

program test2;
{$LONGSTRINGS ON}

uses
   classes;

type
   TURL = class
   private
      FData1 : String;
      FData2 : String;
      procedure SetData1(Value : String);
      procedure SetData2(Value : String);
   public
      property Data1 : String read FData1 write SetData1;
      property Data2 : String read FData2 write SetData2;
   end;
   
procedure TURL.SetData1(Value:String);
begin
   FData1 := Value;
end;

procedure TURL.SetData2(Value:String);
begin
   FData2 := Value;
end;

var
   URL : TURL;

begin
   URL.Data1 := 'abc';
   URL.Data2 := 'def';
end.
 

mvivancoAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

mheacockCommented:
In the LONGSTRINGS ON version, have you tried making the SetData abd SetData1 parameters CONST or VAR?

This may help.
0
mvivancoAuthor Commented:
I tried both Const and Var and the results are the same, GPF!!!

As you can see by the above code, there is nothing strange about the code.  I am just assigning a value to the property variables.  The interesting thing is that if you remove the Set functions and wrote straight to the variables you still get a GPF!  I tried to find the error from the address return in the GPF but it must be in the VCL code because Delphi cannot find it.  Any other ideas?
0
mheacockCommented:
Longstrings cannot be members of records structures.

Classes are nothing more than records structures that contain methods.  You will have to rewrite your class to use PChars instead of Longstrings.  PChars are essentially the same as
Longstrings, but you have to assign memory for them manually and free them manually.  You also cannot do things like

     szName := 'go';
instead do
     StrCopy(szName, 'go');

If you have to use strings, you'll have to use ShortStrings.

See the Delphi help files on TYPES, then click record structures to read about the limitation.  Classes have the same limitation.
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

mvivancoAuthor Commented:
I have just been given the answer to my question and unfortunately your answer was wrong.  The correct answer came from Peter Illes who wrote a paper on converting Delphi 1 code to Delphi 2 (http://ourworld.compuserve.com/homepages/piprog/sgrequ.htm).
Apparently you have to initialize all class instances with a
constructor assignment.  I am investigating it further but so far I have no more GPFs!

Change the main routine as follows:
begin
  // Add the line below and the code will work
  URL := TURL.Create;

  URL.Data1 := 'abc';
  URL.Data2 := 'def';
end.

By the way, I looked in the Delphi help file and the only thing they say is that you cannot have long strings in a variant record.

"Fields in the variant part of a record cannot be of a long string type or of the type Variant. Likewise, fields in the variant part of a record cannot be of a structured type that contains long string or Variant components."
0
mheacockCommented:
Oh well...I'm pretty sure you have to use CREATE in Delphi1
also.  I completely missed your lack of a CREATE call.
0
lkovacCommented:
You need to have the constructor for your object, otherwise strings are not initialized. The long string is basically the four byte pointer. If it is not initially nil (empty) then any assignment (URL.Data1 := 'abc"; for instance) will first try to free the memory pointer is pointing to (which is garbage for you) and that is causing an exception. Constructor will do fine for you in this situation. There may be another situation, you may need to use dynamically allocated strings, like this:
var
  p: pointer;
begin
  GetMem(p, sizeof(string)); {size of long string is 4}
  Initialize(string(p^)); {this will make sure newly allocated string is actually nil pointer initially}
  ... now assign it and use it ...
  Finalize(string(p^)); {this will dealocate memory properly}
  FreeMem(p, sizeof(string));
end;
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mvivancoAuthor Commented:
Your answer is kind of correct.  I don't know that I need a constructor but I do need to add URL := TURL.Create to create the object.  You are right in saying that the string pointer is not initialized which will happen when I create the TURL object.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.