Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.

Commit 6885aa3

Browse files
Merge pull request #419 from xamarin/lets-make-dispose-better
notify on use of disposed object
2 parents 488559e + 753222d commit 6885aa3

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

SwiftReflector/NewClassCompiler.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3693,11 +3693,14 @@ void ImplementIDisposable (ClassDeclaration classDecl, ClassContents contents, C
36933693
// protected virtual void DisposeUnmanagedResources()
36943694
// {
36953695
// SwiftCore.Release(SwiftObject);
3696+
// SwiftObject = IntPtr.Zero;
36963697
// }
36973698
var disposeUnmanaged = new CSMethod (CSVisibility.Protected,
36983699
CSMethodKind.Virtual, CSSimpleType.Void, disposeUnmanagedIdent, new CSParameterList (),
36993700
new CSCodeBlock ()
3700-
.And (CSFunctionCall.FunctionCallLine ("SwiftCore.Release", false, kSwiftObjectGetter)));
3701+
.And (CSFunctionCall.FunctionCallLine ("SwiftCore.Release", false, kSwiftObjectGetter))
3702+
.And (CSAssignment.Assign (kSwiftObjectGetter, CSConstant.IntPtrZero))
3703+
);
37013704
cl.Methods.Add (disposeUnmanaged);
37023705

37033706
var destructor = new CSMethod (CSVisibility.None, CSMethodKind.None, null, csDestructorIdent, new CSParameterList (),

SwiftRuntimeLibrary/SwiftMarshal/StructMarshal.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public static unsafe IntPtr RetainSwiftObject (ISwiftObject obj)
2525
{
2626
if (obj == null)
2727
return IntPtr.Zero;
28+
if (obj.SwiftObject == IntPtr.Zero)
29+
throw new SwiftRuntimeException ("SwiftObject handle is IntPtr.Zero, likely because it was disposed.");
2830
byte* valueBuffer = stackalloc byte [3 * IntPtr.Size];
2931
SwiftCore.swift_beginAccess (obj.SwiftObject, valueBuffer, (uint)SwiftExclusivityFlags.Track, IntPtr.Zero);
3032
var result = SwiftCore.Retain (obj.SwiftObject);

tests/tom-swifty-test/SwiftReflector/NewClassCompilerTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,41 @@ public func reportIt (a: EasyToRepresent) -> Bool {
14981498

14991499
TestRunning.TestAndExecute (swiftCode, callingCode, "Here.Value cannot be null.\nParameter name: a\n");
15001500
}
1501+
1502+
[Test]
1503+
public void CheckOnDisposeThanks ()
1504+
{
1505+
var swiftCode = @"
1506+
public class DisposeMeThanks {
1507+
public init () { }
1508+
public func doIt () -> Int {
1509+
return 77
1510+
}
1511+
}
1512+
public func tryMeHere (a:DisposeMeThanks ) -> Int {
1513+
return a.doIt ()
1514+
}
1515+
";
1516+
// try {
1517+
// var p = new DisposeMeThanks ();
1518+
// p.Dispose ();
1519+
// TopLevelEntities.TryMeHere (p);
1520+
// } catch (Exception err) {
1521+
// Console.WriteLine (err.Message);
1522+
// }
1523+
1524+
var pID = new CSIdentifier ("p");
1525+
var errID = new CSIdentifier ("err");
1526+
var pDecl = CSVariableDeclaration.VarLine (pID, new CSFunctionCall ("DisposeMeThanks", true));
1527+
var disposeCall = CSFunctionCall.FunctionCallLine ($"{pID.Name}.Dispose", false);
1528+
var tryItCall = CSFunctionCall.FunctionCallLine ("TopLevelEntities.TryMeHere", false, pID);
1529+
var catchPrinter = CSFunctionCall.ConsoleWriteLine (errID.Dot (new CSIdentifier ("Message")));
1530+
var tryCatch = new CSTryCatch (CSCodeBlock.Create (pDecl, disposeCall, tryItCall),
1531+
typeof (Exception), errID.Name, CSCodeBlock.Create (catchPrinter));
1532+
var callingCode = CSCodeBlock.Create (tryCatch);
1533+
1534+
TestRunning.TestAndExecute (swiftCode, callingCode, "SwiftObject handle is IntPtr.Zero, likely because it was disposed.\n");
1535+
}
15011536
}
15021537
}
15031538

0 commit comments

Comments
 (0)