Recent

Author Topic: Project raised exception class External:SIGSEGV  (Read 3113 times)

badmintonfan

  • New Member
  • *
  • Posts: 46
Project raised exception class External:SIGSEGV
« on: May 20, 2018, 01:55:46 pm »
I try to create a dll and load it dynamically,but an error message displaied when I call the function
below red font is the code:
library mydll;

{$mode objfpc}{$H+}

uses
  Classes, Windows,WinSock,
  SysUtils,Dialogs
  { you can add units after this };

Function WinUserName(): string; stdcall;
var
   FStr: PChar;
   FSize: Cardinal;
begin
   FSize := 255;
   GetMem(FStr, FSize);
   GetUserName(FStr, FSize);
   Result := FStr;
   FreeMem(FStr);
end;


function myMessage(): string; stdcall;
  begin
     MessageBox(0,PChar('Hello world'),PChar(''),MB_OK);
   end;

exports WinUserName index 1,myMessage index 2;
begin
end.             
the funny thing is, the same code can work properly as a function in my main program

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11351
  • FPC developer.
Re: Project raised exception class External:SIGSEGV
« Reply #1 on: May 20, 2018, 01:57:19 pm »
Passing automated types like strings over DLL borders is not safe.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Project raised exception class External:SIGSEGV
« Reply #2 on: May 20, 2018, 02:28:40 pm »
what marcov said, don't pass strings from dlls, use widestrings for that
Edit:As an after thought how hard it would be to replace the dll's memory manager with the one of your application on load? hmmmm......... it will have to be part of the load process a very visible requirement, oh well something to think about..
« Last Edit: May 20, 2018, 02:39:05 pm by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Mr.Madguy

  • Hero Member
  • *****
  • Posts: 844
Re: Project raised exception class External:SIGSEGV
« Reply #3 on: May 20, 2018, 04:12:10 pm »
Dunno about Lazarus, but in Delphi you would need to include ShareMem as first unit in both main program and DLL project files and provide BorlndMM.dll with your project. Otherwise you would get access violations for no reason. You could also use FastMM directly. I've heard, that it supports sharing memory manager without some DLLs, but I've also heard, that this feature has some problems, such as being unable to run multiple copies of the same program.

I don't know for sure, but, I guess, Lazarus has different RTL and different memory manager, so there should be some other method of sharing memory manager here.
Is it healthy for project not to have regular stable releases?
Just for fun: Code::Blocks, GCC 13 and DOS - is it possible?

ASerge

  • Hero Member
  • *****
  • Posts: 2212
Re: Project raised exception class External:SIGSEGV
« Reply #4 on: May 20, 2018, 08:03:01 pm »
Function WinUserName(): string; stdcall;
var
   FStr: PChar;
   FSize: Cardinal;
begin
   FSize := 255;
   GetMem(FStr, FSize);
   GetUserName(FStr, FSize);
   Result := FStr;
   FreeMem(FStr);
end;

Try this:
Code: Pascal  [Select][+][-]
  1. function WinUserName: ShortString; stdcall;
  2. var
  3.   Size: DWORD;
  4. begin
  5.   Size := SizeOf(Result) - 1;
  6.   if not GetUserName(@Result[1], Size) then
  7.     Size := 1;
  8.   SetLength(Result, Size - 1);
  9. end;

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: Project raised exception class External:SIGSEGV
« Reply #5 on: May 20, 2018, 08:33:26 pm »
This is the standard way of doing it. This allows you to optionally pass a zero size to test for the required size
or just give it a good size chunk and go with it...
Code: Pascal  [Select][+][-]
  1. implementation
  2. Function GetUserNameFromDLL(S:PChar; var Size:LongWord):LongBool;  stdcall;
  3. Begin
  4.    Result := GetUserName(S,Size);
  5. End;
  6.  
  7. {$R *.lfm}
  8.  
  9. { TForm1 }
  10.  
  11. procedure TForm1.Button1Click(Sender: TObject);
  12. Var
  13.    S:string;
  14.    L:LongWord;
  15. begin
  16.    L := 100;
  17.    Setlength(S,L);
  18.    if GetUserNameFromDLL(@S[1],L) Then
  19.     Begin
  20.       SetLength(S, L);
  21.       Caption := S;
  22.     end;
  23. end;                
  24.  

In this example, L returns the actual length of the string and as you can see the string has been truncated after the
fact..

 You can also call this function with L = 0 which will not pass back any string data but will fill L to the actual
size of string needed so one could initiate the string length to that first and then call it again with L now being the
actual size needed.
The only true wisdom is knowing you know nothing

badmintonfan

  • New Member
  • *
  • Posts: 46
Re: Project raised exception class External:SIGSEGV
« Reply #6 on: May 21, 2018, 12:17:07 pm »
what marcov said, don't pass strings from dlls, use widestrings for that
Edit:As an after thought how hard it would be to replace the dll's memory manager with the one of your application on load? hmmmm......... it will have to be part of the load process a very visible requirement, oh well something to think about..
You are right,it works fine with shortstring or widestring,but disagree with string,what's the difference among these types,why only string......
« Last Edit: May 21, 2018, 12:34:13 pm by badmintonfan »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Project raised exception class External:SIGSEGV
« Reply #7 on: May 21, 2018, 01:28:49 pm »
what marcov said, don't pass strings from dlls, use widestrings for that
Edit:As an after thought how hard it would be to replace the dll's memory manager with the one of your application on load? hmmmm......... it will have to be part of the load process a very visible requirement, oh well something to think about..
You are right,it works fine with shortstring or widestring,but disagree with string,what's the difference among these types,why only string......
String is a managed type. It has a reference count and a copy on write logic attach to it. The moment the function exits the dll memory manager sees the string counter drop to 0 and destroys the data.

As for shortstring I assume it works because it uses copy on assignment, the function copies the data to an application provided memory. I never used them this way and I can't test it right now, so be careful with this assumption.

Widestring is an ole type it use an external system dll to manage the memory that both application and dll use and that makes it stable.

Personally I have never used shortstrings to return data I use the same mechanism the windows API uses ee pass a pchar pointer to the external function and the available size, the function returns the required size in bytes if the required size is bigger than the size passed then nothing get copied to the destination pchar, rhe application gets the required size to allocate for the next call to work. if it is smaller then the pchar contains the required string and the application gets to trim the pchar to the data size.


Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

badmintonfan

  • New Member
  • *
  • Posts: 46
Re: Project raised exception class External:SIGSEGV
« Reply #8 on: May 22, 2018, 03:00:39 am »
Thanks everyone,it's solved.

 

TinyPortal © 2005-2018