I am doing a lot of inserts in my sqlite db. For some reason, at a specific point, the app crashes. I checked the insert command - everything is fine.
If I run it on an iPhone 4 device - it runs perfectly.
The problem is that I don't get any error messages, not even memory warnings. xCode seems to still run, but on the device, the app crashes.
This is my code:
sqlite3_stmt *compiledStatement;
for (UpdateItems *one in arrList) {
NSString *stat;
stat = [[NSString alloc] initWithFormat:#"insert into table values (null, (select id from t1 where code='%#'), (select id from t2 where c='%#'), '%#', '%#', '%#', '%#', '%#', '%#')", one.bk, one.code, one.data, one.b, one.bV, one.s, one.sV, one.o];
if(sqlite3_prepare_v2(database, [stat UTF8String], -1, &compiledStatement, NULL) == SQLITE_OK)
{
while(YES){
NSInteger result = sqlite3_step(compiledStatement);
printf("db error: %s\n", sqlite3_errmsg(database));
if(result == SQLITE_DONE){
index = index + 1;
double totalPrc = 0.75f + roundf(((double) index / totalRecords) / (100 / 20) * 100.0f) / 100.0f;
if (self.percentageCompleted != totalPrc) {
self.percentageCompleted = totalPrc;
[self performSelectorOnMainThread:#selector(refreshHUD) withObject:nil waitUntilDone:NO];
}
break;
}
else if(result != SQLITE_BUSY){
printf("db error: %s\n", sqlite3_errmsg(database));
break;
}
}
sqlite3_reset(compiledStatement);
}
[stat release];
}
How can I track this, to see what is the problem?
You might not see anything on xcode console, what about device crash logs ? Whenever there is a crash, crash reporter generates a crash report. Use XCode organizer to bring up device logs, symbolicate them
If the App that crashed was built with: stripping debug symbols - NO:
a nice symbolicated crash log should appear in your organizer window giving a stack trace, etc:
Related
XCode 12.4 , lldb debug on one IOS app
using command 'expression'
(int) printf("hello world\n");
no output ,but
(void) NSLog(#"hello world\n");
it did work , why ? can I change to C/C++ mode ?
enter image description here
also, I find that
(void) NSLog(#"number = %i", 123);
result is "number = 307823584".
i don't know what it means. it seem that only objc object is allowed ?
SString* temp = #"yuv";
(void) NSLog(#"str = %#", temp);
output is "str = yuv" (corret)
but
(void) NSLog(#"str = %s", "123456");
output is "str = »¡#" (error)
There's a similar question for iOS, but I found that the proprosed solutions do not work on macOS in all cases.
On a Mac, there are many possible Trash folders:
/.Trashes
~/.Trash
~/Library/Mobile Documents/com~apple~CloudDocs/.Trash – this one is from iCloud
/Users/xxx/.Trash – any other user's trash
/Volumes/xxx/.Trashes
This code should work but doesn't for the case of the iCloud trash:
NSURL *theURL = ...;
NSURLRelationship relationship = NSURLRelationshipOther;
NSError *error = nil;
[NSFileManager.defaultManager
getRelationship: &relationship
ofDirectory: NSTrashDirectory
inDomain: 0
toItemAtURL: theURL
error: &error];
BOOL insideTrash = !error && (relationship == NSURLRelationshipContains);
If the URL points to any iCloud folder (including the Trash folder shown above), I get this error:
Error Domain=NSCocoaErrorDomain Code=3328
"The requested operation couldn’t be completed because the feature is not supported."
Curiously, even the header file of "NSFileManager" in the 10.15 SDK suggests to use this same code:
/* trashItemAtURL:resultingItemURL:error: [...]
To easily discover if an item is in the Trash, you may use
[fileManager getRelationship:&result ofDirectory:NSTrashDirectory
inDomain:0 toItemAtURL:url error:&error]
&& result == NSURLRelationshipContains.
*/
There also seems to be an issue with trashItemAtURL: on iCloud-synched folders.
So, how do I solve this? If the Finder can detect the iCloud trash, I should be, too.
(Note: The app I use for testing this is not even sandboxed)
More findings: Fails with dead symlinks, too
The officially suggested method of using getRelationship: also fails with an error if the url points to a symlink whose target doesn't exist.
So, basically, this function is quite broken (verified in 10.13.6, 10.15.7 and 11.0.1).
Here's code to demonstrate the bug, which I've filed with Apple under FB8890518:
#import <Foundation/Foundation.h>
static void testSymlink (NSString* symlinkName, NSString* symlinkTarget)
{
NSString *path = [[NSString stringWithFormat:#"~/.Trash/%#", symlinkName] stringByExpandingTildeInPath];
NSURL *url = [NSURL fileURLWithPath:path];
symlink (symlinkTarget.UTF8String, path.UTF8String);
NSLog(#"created symlink at <%#> pointing to <%#>", url.path, symlinkTarget);
NSURLRelationship relationship = -1;
NSError *error = nil;
[NSFileManager.defaultManager getRelationship:&relationship ofDirectory:NSTrashDirectory inDomain:0 toItemAtURL:url error:&error];
NSString *rel = #"undetermined";
if (relationship == 0) rel = #"NSURLRelationshipContains";
if (relationship == 1) rel = #"NSURLRelationshipSame";
if (relationship == 2) rel = #"NSURLRelationshipOther";
NSLog(#"result:\n relationship: %#\n error: %#", rel, error);
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
testSymlink (#"validSymlink", #"/System");
testSymlink (#"brokenSymlink", #"/nonexisting_file");
}
return 0;
}
With the realization that [NSFileManager getRelationship:] even fails for broken symlinks, I conclude that this is a bug in macOS that's been existing undetected for years.
I came up with the following work-around:
Use the getRelationship: operation, then check the returned error first:
If there's no error, then check if relationship == NSURLRelationshipContains, and use that as my result.
Else, in case of any error, check whether the path contains "/.Trash/" or "/.Trashes/" - if so, assume the item is inside the Trash folder.
NSURL *theURL = ...;
NSURLRelationship relationship = NSURLRelationshipOther;
NSError *error = nil;
[NSFileManager.defaultManager
getRelationship: &relationship
ofDirectory: NSTrashDirectory
inDomain: 0
toItemAtURL: theURL
error: &error];
BOOL insideTrash = !error && (relationship == NSURLRelationshipContains)
|| error && (
[theURL.path containsString:#"/.Trash/"]
|| [theURL.path containsString:#"/.Trashes/"]
)
);
I successfully managed to build a complex AUGraph that I'm able to reconfigure on the fly, and all is working well.
I'm facing a wall now with what seems a very simple task: selecting a sepcific output device.
I'm able to get the deviceUID and ID thanks to this post: AudioObjectGetPropertyData to get a list of input devices (that I've modified to get output devices) and to the code below (I can't remember where I've found it, unfortunately)
- (AudioDeviceID) deviceIDWithUID:(NSString *)uid
{
AudioDeviceID myDevice;
AudioValueTranslation trans;
CFStringRef *myKnownUID = (__bridge CFStringRef *)uid;
trans.mInputData = &myKnownUID;
trans.mInputDataSize = sizeof (CFStringRef);
trans.mOutputData = &myDevice;
trans.mOutputDataSize = sizeof(AudioDeviceID);
UInt32 size = sizeof (AudioValueTranslation);
AudioHardwareGetProperty (kAudioHardwarePropertyDeviceForUID,
&size,
&trans);
return myDevice;
}
I'm getting the AudioDeviceID from this method which I store in an NSDictionary. I can NSLog it and when I convert it in hexadecimal it gives me the right ID, found in HALLab.
But when I configure my unit (see code below) the graph only plays on the default device (the one selected in Sound Preferences).
AudioComponent comp = AudioComponentFindNext(NULL, &_componentDescription);
if (comp == NULL) {
printf ("Can't get output unit");
exit (-1);
}
CheckError(AudioComponentInstanceNew(comp, &_auUnit),
"Couldn't open component for output Unit");
UInt32 disableFlag = 0;
UInt32 enableFlag = 1;
AudioUnitScope outputBus = 0;
AudioUnitScope inputBus = 1;
CheckError (AudioUnitSetProperty(_auUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
outputBus,
&enableFlag,
sizeof(enableFlag)), "AudioUnitSetProperty[kAudioOutputUnitProperty_EnableIO] failed - enable Output");
CheckError (AudioUnitSetProperty(_auUnit,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
inputBus,
&disableFlag,
sizeof(disableFlag)), "AudioUnitSetProperty[kAudioOutputUnitProperty_EnableIO] failed - disable Input");
AudioDeviceID devID = (AudioDeviceID)[[[_devices objectAtIndex:0] objectForKey:#"deviceID"] unsignedIntValue];
CheckError(AudioUnitSetProperty(_auUnit,
kAudioOutputUnitProperty_CurrentDevice,
kAudioUnitScope_Output,
0,
&devID,
sizeof(AudioDeviceID)), "AudioUnitSetProperty[kAudioOutputUnitProperty_CurrentDevice] failed");
The AUGraph is already configured with all units, nodes are connected, and it's open. What am I doing wrong ?
I would be very grateful for any clue to resolve this problem.
I am writing a Cocoa application which uses bluetooth. I am trying to connect to a bluetooth device but it fails.
IOBluetoothDevice *btDevice;
// I do search and find the device
btDevice = ;//device found
//btDevice is not nil
IOReturn status = [btDevice openConnection];
if (status != kIOReturnSuccess) {
NSLog( #"Error - failed to connect. %d", status );
}
And I get the device when searches, but openConnection method fails. And NSLog prints
Error = failed to connect. 4
Now what this error code indicates?
I looked at IOKit.framework/IOReturn.h file and it shows many error codes
#define kIOReturnError iokit_common_err(0x2bc) // general error
#define kIOReturnNoMemory iokit_common_err(0x2bd) // can't allocate memory
#define kIOReturnNoResources iokit_common_err(0x2be) // resource shortage
#define kIOReturnIPCError iokit_common_err(0x2bf) // error during IPC
#define kIOReturnNoDevice iokit_common_err(0x2c0) // no such device
.......
//And many more
And I wrote a function to identify what is error code 4
- (void)logError:(OSStatus)status{
if (status == kIOReturnError) {
NSLog(#"kIOReturnError");
}else if(status == kIOReturnNoMemory){
NSLog(#"kIOReturnNoMemory");
}else if(status == kIOReturnNoResources){
NSLog(#"kIOReturnNoResources");
}else if(status == kIOReturnIPCError){
NSLog(#"kIOReturnIPCError");
}else if(status == kIOReturnNoDevice){
......
......
}else{
NSLog(#"No price for you");
}
}
And it prints
No price for you
What does error code 4 imply? Also is there any easier way to identify error reason from OSStatus error codes?
[IOBluetoothDevice openConnection] returns an IOReturn code (which is a I/O Kit specific error number) while your logError: method tests for OSStatus codes.
OSStatus is not the same as IOReturn.
Apple has a Technical Q&A that explains the macros to lookup I/O Kit errors.
http://developer.apple.com/library/mac/#qa/qa1075/_index.html
In your case it seems to be a Mach error (that's probably the 0x4 hi bits of the error that show up as decimal 4 in your log line).
I think the 4 response is actually kBluetoothHCIErrorPageTimeout. The only code I've found that uses this is this: https://www.ida.liu.se/~TDDD63/projects/2013/mindstorms/Installation/Mac/lightblue-0.4-master/src/mac/_bluetoothsockets.py
I've got a Cocoa command-line app which is built to target 10.5 SDK. In the app, I have
NSString *appPath = [[NSBundle mainBundle] bundlePath];
NSLog(#"%#", appPath);
On Mac OSX 10.5, when I run the app from the command line, I get the expected output of the path. However, if I set the app up to run as a LaunchDeamon, it only outputs a '/'
It works as expected on 10.6 and on 10.7 both as a Deamon and as an app. Anyone know why the difference would be? Is there a better way to get the application path that would work on 10.5+?
UPDATE
For me, the solution in the accepted answer did not work. However, the comment about adding the "WorkingDirectory" key to the LaunchDeamon's plist file worked out. Apparently this is needed for Mac OS X 10.5, but not 10.6+.
Thanks for answering my clarifying question.
NSBundle depends on a existing bundle, with it's associated Info.plists and bundle ID's (e.g. com.apple.textedit.app), etc.
While a single binary is not a bundle, I'm guessing that Apple engineering fixed up [[NSBundle mainBundle] bundlePath] to do "the right thing" in 10.6 & 10.7. But you still need a solution for 10.5.
Maybe the UNIX library function char * getcwd(char *buf, size_t size) would get you to where you need to be.
For a proper solution, I'd recommend doing a run-time conditional check with code that looks something like this:
+ (NSString *) getAppPath
{
NSString * appPath = NULL;
SInt32 minorVersionNum;
OSErr err;
err = Gestalt(gestaltSystemVersionMinor,&minorVersionNum);
// do this only if we're running on anything *older* than 10.6
if((noErr == err) && (minorVersionNumber < 6))
{
// hopefully the below define is enough space for any returned path
#define kMaxPathLength 512
size_t bufferLength = kMaxPathLength;
char bufferToHoldPath[kMaxPathLength];
// initialize the buffer & guarantee null-terminated strings
bzero(&bufferToHoldPath,bufferLength);
if( getcwd(&bufferToHoldPath, bufferLength) != NULL)
{
appPath = [NSString stringWithUTF8String: bufferToHoldPath];
}
}
// this code runs for 10.6 and *newer*, and attempts it on
// 10.5 only if the above getcwd call failed
if(NULL == appPath)
{
appPath = [[NSBundle mainBundle] bundlePath];
}
return(appPath);
}
I did not test this code out so YMMV.