JuliaInterop / ObjectiveC.jl

Objective-C embedded in Julia
Other
39 stars 10 forks source link

NSArray can be constructed with non-NSObjects, leading to segfaults #25

Closed christiangnrd closed 5 months ago

christiangnrd commented 5 months ago

Doesn't segfault when creating an array of strings as shown in the example (or dict for that matter), but for other objects it crashes.

MWE:

julia> using ObjectiveC, .Foundation, Metal

julia> d = current_device()
<AGXG14CDevice: 0x13c04a800>
    name = Apple M2 Max

julia> d isa NSObject
true

julia> a = MTLFence(d)
<IOGPUMetalFence: 0x600002278060>

julia> a isa NSObject
true

julia> NSArray([d,d])
<__NSArrayI 0x6000004481e0>(
<AGXG14CDevice: 0x13c04a800>
    name = Apple M2 Max,
<AGXG14CDevice: 0x13c04a800>
    name = Apple M2 Max
)

julia> NSArray([a,a])

[36456] signal (11.2): Segmentation fault: 11
in expression starting at REPL[5]:1
objc_msgSend at /usr/lib/libobjc.A.dylib (unknown line)
__NSArrayI_new at /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (unknown line)
Allocations: 5428130 (Pool: 5421602; Big: 6528); GC: 9
objc[36456]: Attempt to use unknown class 0x600000b86130.

[36456] signal (6): Abort trap: 6
in expression starting at REPL[5]:1
__abort_with_payload at /usr/lib/system/libsystem_kernel.dylib (unknown line)
Allocations: 5428130 (Pool: 5421602; Big: 6528); GC: 9
Abort trap: 6
maleadt commented 5 months ago

NSArray only supports NSObjects, so you can't use NSUInteger (which is a plain UInt) but you should use NSNumber:

julia> a = NSNumber(42)
+ [NSNumber numberWithInteger: 42]
  (id<NSNumber>)0x8aaa94e3f4001b01
- [(id<NSObject>)0x8aaa94e3f4001b01 debugDescription]
  (id<NSString>)0x8aaa94e3f419140c
- [(id<NSString>)0x8aaa94e3f419140c UTF8String]
  (Int8*)0x0000600001d21f48
42

julia> NSArray([a, a])
+ [NSArray arrayWithObjects:count: (id*)0x000000010beeefc0 0x0000000000000002]
  (id<NSArray>)0x0000600001d10f60
- [(id<NSObject>)0x0000600001d10f60 debugDescription]
  (id<NSString>)0x0000600001306ee0
- [(id<NSString>)0x0000600001306ee0 UTF8String]
  (Int8*)0x0000600003624110
<__NSArrayI 0x600001d10f60>(
42,
42
)

Our NSArray wrapper could be more careful about this, but more work is needed for parametric containers in general.

christiangnrd commented 5 months ago

My MWE was too simplified for what I was actually trying to fix. I've edited my MWE to better represent the issue.

Seems like it crashes for NSObjects that have immutable=false in their `@objcwrapper definition.

christiangnrd commented 5 months ago

This works however:

julia>  NSArray([a.ptr,a.ptr])
<__NSArrayI 0x600002c61400>(
<IOGPUMetalFence: 0x600002278060>,
<IOGPUMetalFence: 0x600002278060>
)

Is this something that should be fixed?

maleadt commented 5 months ago

Hmm, that does make me realize that the current conversion of Vector{NSNumber} to Ptr{id{Object}} only happens to work because the NSNumber struct in Julia only contains a pointer field... (which is also why passing an array of pointers works)

I'll see if I can do a quick fix, but otherwise this would probably better wait for a redesign of parametric types.