I've been receiving SIGSEGV (11)
exceptions in multi-platform apps with seemingly simple code. Debugger seems to take me to a different place each time this happens. So I threw together a simple app to demonstrate this. It does not happen in Windows, but it does happen on all other platforms. Windows works fine. This only example I'm able to recreate every time and demonstrate below comes from the XSuperObject
library.
Start a new blank Multi-platform application and add just one button.
DFM
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 259
ClientWidth = 310
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
DesignerMasterStyle = 0
object Button1: TButton
Position.X = 136.000000000000000000
Position.Y = 96.000000000000000000
TabOrder = 0
Text = 'Button1'
OnClick = Button1Click
end
end
Now add just a handler for this button's OnClick
event.
CODE
unit uMain;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
XSuperObject;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
uses
IOUtils;
procedure TForm1.Button1Click(Sender: TObject);
var
O: ISuperObject;
L: TStringList;
FN: String;
begin
FN:= TPath.Combine(TPath.GetHomePath, 'MyApp');
ForceDirectories(FN);
FN:= TPath.Combine(FN, 'Test.json');
O:= SO;
O.S['foo']:= 'bar';
L:= TStringList.Create;
try
L.Text:= O.AsJSON(True);
L.SaveToFile(FN);
finally
L.Free;
end;
O:= TSuperObject.ParseFile(FN); // <-- SIGSEGV (11) happens here
end;
end.
On a test with OSX, for example, pressing the button produces the exception:
Project SIGSEGVTest raised exception class SIGSEGV (11).
When I click on Break
, it takes me into some System.Character.inc
file on line 1394
, which appears to be a bunch of binary of some sort:
db $59,$40,$00,$00,$00,$00,$00,$40,$8F,$40,$00,$00,$00,$00,$00
In some cases, I get this exception repeatedly for what appears to be infinitely. I can't seem to trace where it's coming from. I'm not having any luck searching for this, everything I find is either in another language, unanswered, or for another pascal IDE (such as Lazarus). Every now and then, in the same scenario as above, the app just locks up rather than giving this exception. Also sometimes, the debugger doesn't take me anywhere when I click Break
.
I do understand what the exception means (essentially the same as Access Violation), but why am I getting this exception on all platforms other than Windows?
NOTE
I did manage to fix this in one place in the past by using the generics TList<>
rather than the traditional deprecated TList
. But that's just one, and I'm struggling to find out the actual reason I'm getting this exception in so many places. Been battling it for weeks now.
I'm using Delphi XE7 Update 2, and my copy of XSuperObject
was just updated right now with the latest, but no luck.
I also installed the latest IDE Fix Pack and still no luck.
UPDATE
When, for example, running this same app from within an iOS simulator (iOS 7.1) without debug, I get the following:
Access violation at address 0060907D, accessing address 00000000.
UPDATE
Here's the crash report from OSX (too big to fit in here):
UPDATE
It almost seems as if pointers are becoming corrupted somehow. In most cases I've seen so far, it happens when I'm accessing a pointer which should be initialized. For example, when I had a classic TList, it let me use it just fine, except when I tried to read one of the pointers and I got this same error. Same exact code works perfect in Windows. For example, MyObj:= TMyObj(MyTList[0]);
where I can see the correct pointer is there, but produces this exception anyway. Unfortunately, since I've tried to reproduce this particular scenario, I cannot.
UPDATE
I just finally managed to step through the XSuperObject
library (previously I was getting other strange issues while trying to set a breakpoint to step through). It breaks on line 587 which is inside the following constructor:
constructor TBaseJSON<T, Typ>.Create(JSON: String; const CheckDate: Boolean);
type PInterface = ^IInterface;
var
JVal: IJSONAncestor;
PIntf: PInterface;
begin
FCheckDate := CheckDate;
if (Self.InheritsFrom(TSuperArray)) and (Trim(JSON) = '{}') then JSON := '[]';
JVal := TJSONObject.ParseJSONValue(JSON, FCheckDate);
if JVal.QueryInterface(GetTypeData(TypeInfo(T)).Guid, FJSONObj) = S_OK then // <-- Happens here
FInterface := TValue.From<T>(FJSONObj).AsInterface
else
FCasted := JVal
end;