Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 10 total
Thread Major D2006 / DBISAM problem
Wed, Apr 19 2006 2:20 PMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

TIM

Try this code - eSesh is assigned on entry into the event.


function GetWindowsTempPath: string;
var
TempPathName: array[0..250] of Char;
begin
try
 if GetTempPath(250, TempPathName) <> 0
  then Result := TempPathName
 else begin
  ForceDirectories('C:\Temp');
  Result := 'C:\Temp';
 end;
except
 ForceDirectories('C:\Temp');
 Result := 'C:\Temp';
end;
end;

function MakeDBISAMSession: TDBISAMSession;
begin
Result := TDBISAMSession.Create(nil);
Result.PrivateDir := GetWindowsTempPath;
Result.AutoSessionName := True;
Result.LockProtocol := lpPessimistic;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
eSesh: TDBISAMSession;
begin
if  Assigned(eSesh) then showmessage('OH HELL!');
if not Assigned(eSesh) then eSesh := MakeDBISAMSession;
if Assigned(eSesh) then FreeAndNil(eSesh);
end;


Roy Lambert
Wed, Apr 19 2006 5:47 PMPermanent Link

"Hannes Danzl[NDD]"
Roy Lambert wrote:

> TIM
>
> Try this code - eSesh is assigned on entry into the event.

I'd assume you get a warning from the compiler about esesh ...

That's not a DBIsam problem, but a different handling of D2006 in regards of
uninitialized variables. You should always initialize anyways ....

--

Hannes Danzl [NexusDB Developer]
Newsgroup archive at http://www.tamaracka.com/search.htm
Wed, Apr 19 2006 6:09 PMPermanent Link

"Ralf Mimoun"
Roy Lambert wrote:
> TIM
>
> Try this code - eSesh is assigned on entry into the event.

Never ever rely on the compiler to initialize anything. The eSesh is a
pointer and can contain any value from 0 to $FFFFFFFF. Something might be
initialized by some Delphi versions, but I go the old Turbo Pascal way:
everything is dangling around until I take care of it.

Ralf
Thu, Apr 20 2006 3:02 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Hannes


OK I was going to do some more experimentation this morning because I suspected this might be the case. I'll also post on the delphi groups. Any idea when the behaviour of Assigned changed?

Roy Lambert
Thu, Apr 20 2006 3:32 AMPermanent Link

"Hannes Danzl[NDD]"
Roy Lambert wrote:

> Hannes
>
>
> OK I was going to do some more experimentation this morning because I
> suspected this might be the case. I'll also post on the delphi groups. Any
> idea when the behaviour of Assigned changed?

It's not assigned that has changed. It's just that the local var is not
defined. Actually that assigned check is useless because you're checking the
value of a local variable, the state of which is undefined at this point in
time.

--

Hannes Danzl [NexusDB Developer]
Newsgroup archive at http://www.tamaracka.com/search.htm
Thu, Apr 20 2006 4:33 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Hannes



Weirder and weirder. The test case I posted doesn't work in D6 either, but the app does. I've just stepped over the line

if not Assigned(eSesh) then eSesh := MakeDBISAMSession;

and it works perfectly in D6 but not D2006

If you feel helpful do you have any idea why?

Roy Lambert


function EncodeEMail(eMail: TDBISAMTable): boolean;
var
Encoded: TMimeMess;
sl: TStringList;
MimePart: TMimePart;
Pics: TMimePart;
MsgOpts: TMsgOpts;
eSesh: TDBISAMSession;
ms: TMemoryStream;
Style: string;
procedure AddAttachments;
var
 eAtts: TDBISAMTable;
begin
 if not eMail.FieldByName('_Attachments').IsNull then begin
  if not Assigned(eSesh) then eSesh := MakeDBISAMSession;
  eAtts := MakeDBISAMTable(MakeImgAttMemTable('enc', 'A', eSesh), 'Memory', eSesh);
  StreamMemoToTable('_Attachments', eMail, eAtts);
  eAtts.First;
  while not eAtts.Eof do begin
   ms := TMemoryStream.Create;
   TMemoField(eAtts.FieldByName('_Item')).SaveToStream(ms);
   Encoded.AddPartBinary(ms, ExtractFileName(eAtts.FieldByName('_Name').AsString), MimePart);
   ms.Free;
   eAtts.Next;
  end;
  ZapInMemoryTable(eAtts);
 end;
end;
procedure AddImages;
var
 ePics: TDBISAMTable;
begin
 if not eMail.FieldByName('_InLine').IsNull then begin
  Pics := Encoded.AddPartMultipart('related', MimePart);
  if not Assigned(eSesh) then eSesh := MakeDBISAMSession;
  ePics := MakeDBISAMTable(MakeImgAttMemTable('enc', 'I', eSesh), 'Memory', eSesh);
  StreamMemoToTable('_InLine', eMail, ePics);
  ePics.First;
  while not ePics.Eof do begin
   ms := TMemoryStream.Create;
   TMemoField(ePics.FieldByName('_Item')).SaveToStream(ms);
   Encoded.AddPartHTMLBinary(ms, ExtractFileName(ePics.FieldByName('_Name').AsString), ePics.FieldByName('_CID').AsString, Pics);
   ms.Free;
   ePics.Next;
  end;
  ZapInMemoryTable(ePics);
 end;
end;
begin
MsgOpts := TMsgOpts.Create;
MsgOpts.Options.Assign(eMail.FieldByName('_TMaN'));
sl := TStringList.Create;
if eMail.FieldByName('_PlainText').AsBoolean then begin
 if eMail.FieldByName('_Attachments').IsNull then begin
  sl.Assign(eMail.FieldByName('_Headers'));
  AddCurrentDate(sl);
  sl.Add('');
  if not eMail.FieldByName('_Message').IsNull then sl.Add(eMail.FieldByName('_Message').AsString) else sl.Add(' ');
   {
  MailMsg := eMail.FieldByName('_Message').AsString;
  MailMsg := StringReplace(MailMsg, '<', '&lt;', [rfReplaceAll]);
  MailMsg := StringReplace(MailMsg, '>', '&gt;', [rfReplaceAll]);
  sl.Add(MailMsg);
  }
  eMail.FieldByName('_Encoded').Assign(sl);
 end else begin
  Encoded := TMimemess.Create;
  sl.Assign(eMail.FieldByName('_Headers'));
  Encoded.Header.DecodeHeaders(sl);
  sl.Assign(eMail.FieldByName('_Message'));
  MimePart := Encoded.AddPartMultipart('mixed', nil);
  Encoded.AddPartText(sl, MimePart);
  AddAttachments;
  Encoded.EncodeMessage;
  eMail.FieldByName('_Encoded').Assign(Encoded.Lines);
  Encoded.Free;
 end;
end else begin
 Encoded := TMimemess.Create;
 sl.Assign(eMail.FieldByName('_Headers'));
 Encoded.Header.DecodeHeaders(sl);
 sl.Assign(eMail.FieldByName('_Message'));
 if MsgOpts.CSS then begin
  if 0 = Pos('class="', LowerCase(sl.Text)) then Style := BasicMailStyle else Style := MailStyle;
  sl.Text := '<html><head><style type="text/css">' + Style + '</style></head><body>' + sl.Text + '</body></html>';
 end else begin
  sl.Text := StringReplace(sl.Text, '<p>' + #13#10, '', [rfReplaceAll, rfIgnoreCase]);
  sl.Text := StringReplace(sl.Text, '</p>' + #13#10, '<br/>', [rfReplaceAll, rfIgnoreCase]);
  sl.Text := '<html><body>' + sl.Text + '</body></html>';
 end;
 MimePart := Encoded.AddPartMultipart('mixed', nil);
 Encoded.AddPartHTML(sl, MimePart);
 AddAttachments;
 AddImages;
 Encoded.EncodeMessage;
 eMail.FieldByName('_Encoded').Assign(Encoded.Lines);
 Encoded.Free;
end;
if Assigned(eSesh) then FreeAndNil(eSesh);
MsgOpts.Free;
sl.Free;
eMail.FieldByName('_Size').AsInteger := Length(eMail.FieldByName('_Encoded').AsString);
end;
Thu, Apr 20 2006 11:41 AMPermanent Link

Sean McCall
Roy,

It was probably uninitialized in D6, but through luck in the
D6 compilation the memory that was re-used by the variable /
pointer was nil (all zeros) when some other code was
finished with it and that way the session pointer was
initialized by MakeDBISAMSession. I'm actually surprised
that you didn't get a compiler warning about eSesh being
uninitialized or didn't get an access violation when it was
pointing to some other object or random memory.

Anyway, you should always initialize local variables.. they
are never set to nil like an object field. Also, the code
makes no sense... how could eSesh be a valid dbisam session
when it is a local variable and there is no prior code that
could possibly have set it to point to a TDBISAMSession?
Maybe this variable used to be global and you changed it to
being local? The code should read:

if not eMail.FieldByName('_Attachments').IsNull then begin
   eSesh := MakeDBISAMSession;

HTH,

Sean


Roy Lambert wrote:
> Hannes
>
>
>
> Weirder and weirder. The test case I posted doesn't work in D6 either, but the app does. I've just stepped over the line
>
> if not Assigned(eSesh) then eSesh := MakeDBISAMSession;
>
> and it works perfectly in D6 but not D2006
>
> If you feel helpful do you have any idea why?
>
> Roy Lambert
>
>
> function EncodeEMail(eMail: TDBISAMTable): boolean;
> var
> Encoded: TMimeMess;
> sl: TStringList;
> MimePart: TMimePart;
> Pics: TMimePart;
> MsgOpts: TMsgOpts;
> eSesh: TDBISAMSession;
> ms: TMemoryStream;
> Style: string;
> procedure AddAttachments;
> var
>   eAtts: TDBISAMTable;
> begin
>   if not eMail.FieldByName('_Attachments').IsNull then begin
>    if not Assigned(eSesh) then eSesh := MakeDBISAMSession;
>    eAtts := MakeDBISAMTable(MakeImgAttMemTable('enc', 'A', eSesh), 'Memory', eSesh);
>    StreamMemoToTable('_Attachments', eMail, eAtts);
>    eAtts.First;
>    while not eAtts.Eof do begin
>     ms := TMemoryStream.Create;
>     TMemoField(eAtts.FieldByName('_Item')).SaveToStream(ms);
>     Encoded.AddPartBinary(ms, ExtractFileName(eAtts.FieldByName('_Name').AsString), MimePart);
>     ms.Free;
>     eAtts.Next;
>    end;
>    ZapInMemoryTable(eAtts);
>   end;
> end;
> procedure AddImages;
> var
>   ePics: TDBISAMTable;
> begin
>   if not eMail.FieldByName('_InLine').IsNull then begin
>    Pics := Encoded.AddPartMultipart('related', MimePart);
>    if not Assigned(eSesh) then eSesh := MakeDBISAMSession;
>    ePics := MakeDBISAMTable(MakeImgAttMemTable('enc', 'I', eSesh), 'Memory', eSesh);
>    StreamMemoToTable('_InLine', eMail, ePics);
>    ePics.First;
>    while not ePics.Eof do begin
>     ms := TMemoryStream.Create;
>     TMemoField(ePics.FieldByName('_Item')).SaveToStream(ms);
>     Encoded.AddPartHTMLBinary(ms, ExtractFileName(ePics.FieldByName('_Name').AsString), ePics.FieldByName('_CID').AsString, Pics);
>     ms.Free;
>     ePics.Next;
>    end;
>    ZapInMemoryTable(ePics);
>   end;
> end;
> begin
> MsgOpts := TMsgOpts.Create;
> MsgOpts.Options.Assign(eMail.FieldByName('_TMaN'));
> sl := TStringList.Create;
> if eMail.FieldByName('_PlainText').AsBoolean then begin
>   if eMail.FieldByName('_Attachments').IsNull then begin
>    sl.Assign(eMail.FieldByName('_Headers'));
>    AddCurrentDate(sl);
>    sl.Add('');
>    if not eMail.FieldByName('_Message').IsNull then sl.Add(eMail.FieldByName('_Message').AsString) else sl.Add(' ');
>     {
>    MailMsg := eMail.FieldByName('_Message').AsString;
>    MailMsg := StringReplace(MailMsg, '<', '&lt;', [rfReplaceAll]);
>    MailMsg := StringReplace(MailMsg, '>', '&gt;', [rfReplaceAll]);
>    sl.Add(MailMsg);
>    }
>    eMail.FieldByName('_Encoded').Assign(sl);
>   end else begin
>    Encoded := TMimemess.Create;
>    sl.Assign(eMail.FieldByName('_Headers'));
>    Encoded.Header.DecodeHeaders(sl);
>    sl.Assign(eMail.FieldByName('_Message'));
>    MimePart := Encoded.AddPartMultipart('mixed', nil);
>    Encoded.AddPartText(sl, MimePart);
>    AddAttachments;
>    Encoded.EncodeMessage;
>    eMail.FieldByName('_Encoded').Assign(Encoded.Lines);
>    Encoded.Free;
>   end;
> end else begin
>   Encoded := TMimemess.Create;
>   sl.Assign(eMail.FieldByName('_Headers'));
>   Encoded.Header.DecodeHeaders(sl);
>   sl.Assign(eMail.FieldByName('_Message'));
>   if MsgOpts.CSS then begin
>    if 0 = Pos('class="', LowerCase(sl.Text)) then Style := BasicMailStyle else Style := MailStyle;
>    sl.Text := '<html><head><style type="text/css">' + Style + '</style></head><body>' + sl.Text + '</body></html>';
>   end else begin
>    sl.Text := StringReplace(sl.Text, '<p>' + #13#10, '', [rfReplaceAll, rfIgnoreCase]);
>    sl.Text := StringReplace(sl.Text, '</p>' + #13#10, '<br/>', [rfReplaceAll, rfIgnoreCase]);
>    sl.Text := '<html><body>' + sl.Text + '</body></html>';
>   end;
>   MimePart := Encoded.AddPartMultipart('mixed', nil);
>   Encoded.AddPartHTML(sl, MimePart);
>   AddAttachments;
>   AddImages;
>   Encoded.EncodeMessage;
>   eMail.FieldByName('_Encoded').Assign(Encoded.Lines);
>   Encoded.Free;
> end;
> if Assigned(eSesh) then FreeAndNil(eSesh);
> MsgOpts.Free;
> sl.Free;
> eMail.FieldByName('_Size').AsInteger := Length(eMail.FieldByName('_Encoded').AsString);
> end;
>
Thu, Apr 20 2006 12:13 PMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Sean


I've been well and truly roasted in the borland ng as well. I accept how assigned works (I don't have any choice) but that doesn't mean I have to like it Smiley

Also if its good practice to initialise local variables why doesn't the compiler do it? Is it as lazy as I am?

<<Also, the code
makes no sense... how could eSesh be a valid dbisam session
when it is a local variable and there is no prior code that
could possibly have set it to point to a TDBISAMSession?>>

You're right at this point (AddAttachments), but in AddImages it could have been assigned in AddAttachments, but I'll have to change the code there as well <boo hoo>

<<Maybe this variable used to be global and you changed it to
being local? The code should read:

if not eMail.FieldByName('_Attachments').IsNull then begin
   eSesh := MakeDBISAMSession;>>

Its always been local, been running for about 18 months the procedure is called from several forms and a background thread and hasn't given any trouble.



Roy Lambert
Thu, Apr 20 2006 1:17 PMPermanent Link

Sean McCall
Roy,

I think the compiler doesn't initialize local variables
because it is inefficient. Most of the time local variables
need to be assigned a value to be of any use. The most
common exceptions can think of are numeric and string values
that are used to perform calculations. I would venture to
guess that for performance reasons this is also probably
part of the original Pascal language specification by
Nicholas Wirth... I'd have to poke around in the attic for
my college texts to be sure but I seem to remember that the
language specification was pretty specific.

Sean



Roy Lambert wrote:
> Sean
>
>
> I've been well and truly roasted in the borland ng as well. I accept how assigned works (I don't have any choice) but that doesn't mean I have to like it Smiley
>
> Also if its good practice to initialise local variables why doesn't the compiler do it? Is it as lazy as I am?
>
> <<Also, the code
> makes no sense... how could eSesh be a valid dbisam session
> when it is a local variable and there is no prior code that
> could possibly have set it to point to a TDBISAMSession?>>
>
> You're right at this point (AddAttachments), but in AddImages it could have been assigned in AddAttachments, but I'll have to change the code there as well <boo hoo>
>
> <<Maybe this variable used to be global and you changed it to
> being local? The code should read:
>
> if not eMail.FieldByName('_Attachments').IsNull then begin
>     eSesh := MakeDBISAMSession;>>
>
> Its always been local, been running for about 18 months the procedure is called from several forms and a background thread and hasn't given any trouble.
>
>
>
> Roy Lambert
>
Thu, Apr 20 2006 1:30 PMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Sean


I should have realised - after all Windows programming is ALL about efficiency isn't it <v v b g>

Roy Lambert
Image