Forum Archive

Mysterious Crash

blmacbeth

I have a script where I'm trying to get the system attributes; eventually this will gather memory information. I have isolated the crash to this line of code:

from ctypes import POINTER
from objc_util import ObjCClass, ObjCInstance, c, c_void_p


NSHomeDirectory = c.NSHomeDirectory
NSHomeDirectory.restype = c_void_p
NSHomeDirectory.argtype = []

NSFileManager = ObjCClass('NSFileManager')

LP_c_void_p = POINTER(c_void_p)

def get_system_attributes():
    file_manager = NSFileManager.defaultManager()
    error = LP_c_void_p()
    attributes = file_manager.attributesOfFileSystemForPath_error_(
        ObjCInstance(
            NSHomeDirectory()
        ).cString(),
        error
    )
    return attributes

get_system_attributes()

attributesOfFileSystemForPath_error_ takes a string and an error pointer. It crashes when it gets to the error inside that function. I think it crashes due to an NSError object being created. Any ideas on how to stop the crash?

omz

The crash seems to come from your cString() call. The method expects an NSString object, and you already have that, so simply removing .cString() should fix the crash.

omz

Btw, if you're not actually interested in the error, you can also just pass None for that (you could still detect failure by checking if the return value is None; you only need the error pointer if you want details about the failure).

Cethric

To add on to what @omz said I also saw a crash with the error variable as well.
Here is my fix:

path = ObjCInstance(NSHomeDirectory())
file_manager = NSFileManager.defaultManager()
error = c_void_p()
a = file_manager.attributesOfFileSystemForPath_error_(path, pointer(error))
print(ObjCInstance(error))
print(a)

The only major change that I made was to use ctypes.pointer instead of ctypes.POINTER as the upper case version is for defining argtypes and restypes or values in structures where as the lower case version is used for creating pointer objects

omz

@Cethric I think byref(error) would be a little faster (at least that's what the ctypes docs say).

Cethric

Good catch, I can't say I have done a speed test on iOS to see the differences between the two, but in general yes byref(error) is faster than pointer(error)

blmacbeth

@omz and @Cethric thanks for the help. It seems to work.