Rob
Your suggested code changes worked as advertised..

Best wishes Ed
--- In [email protected], Rob Kennedy <[EMAIL PROTECTED]> wrote:
>
> edsynergy wrote:
> > Here is a small function that extracts a string from a resource dll.
> > Works fine when the resource is there, and I get an EResNotFound When
> > one is not found. However when the code in the exception clause is run
> > (on EResNotFound do Result:= blank;) it immetiately gives an AV. In
> > fact it dos'nt matter what code I put in the exception I get the AV
> > I cant see what the problem is 
> > 
> > Best wishe Ed.
> > 
> > function TformMainTasks.SetAnchorText(const ResString:string):string;
> > var
> >   ls:Tstringlist;
> >   ms:TresourceStream;
> >   h:Thandle;
> > begin
> > 
> > try
> >   h := LoadLibrary(pchar('strings.dll'));
> 
> Do not type-cast a string literal to PChar. The compiler already 
> recognizes when a PChar is required. It only needs a hint like that
when 
> overload resolution might pick the wrong function. LoadLibrary isn't 
> overloaded.
> 
> >   try
> >     ms:=TresourceStream.Create(h,ResString, RT_RCDATA);
> >     if ( Assigned(ms)) then
> 
> That conditional will never fail. The constructor of a class will never 
> return nil. If there is a problem allocating an object, you'll get an 
> exception, in which case no value gets assigned to the variable at all.
> 
> >       begin
> >         try
> >           ls:= TstringList.Create;
> >           ms.Position:= 0;
> >           ls.LoadFromStream(ms);
> >           Result:= ls.Text;
> >         finally
> >           ls.Free;
> >           // free resources
> >         end;  // try/finally
> >       End
> >     Else Result:= blank;
> >   except
> >   on EResNotFound do Result:= blank;
> >   end;  // try/except
> > finally
> >   ms.Free;
> >   FreeLibrary(h);
> > 
> >     // free resources
> > end;  // try/finally
> 
> Never ignore a compiler warning. In your code, you should have gotten 
> warnings in the "finally" blocks suggesting that ls, ms, and h might
not 
> be initialized. The problem stems from misusing the try-finally
block. A 
> try-finally sequence should always have this structure:
> 
> AcquireResource;
> try
>    UseResource;
> finally
>    ReleaseResource;
> end;
> 
> In your code, you enter the try-finally block and *then* you acquire a 
> handle to the DLL, and it's even later before you acquire a 
> TResourceStream object. You mustn't enter a try-finally block until 
> you've successfully acquired the thing that the try-finally block is 
> meant to protect.
> 
> Try this code instead:
> 
> function TFormMainTasks.SetAnchorText(const ResString: string): string;
> var
>    ls: TStringList;
>    ms: TResourceStream;
>    h: THandle;
> begin
>    h := LoadLibrary('strings.dll');
>    Win32Check(h <> 0);
>    try
>      try
>        ms := TResourceStream.Create(h, ResString, RT_RCDATA);
>        try
>          ls := TStringList.Create;
>          try
>            ls.LoadFromStream(ms);
>            Result := ls.Text;
>          finally
>            ls.Free;
>          end;
>        finally
>          ms.Free;
>        end;
>      except
>        on EResNotFound do
>          Result := blank;
>      end;
>    finally
>      FreeLibrary(h);
>    end;
> end;
> 
> -- 
> Rob
>


Reply via email to