I am experiencing frequent crashing that I believe is related to this method of checking the number of MIDINetwork Sessions.
- (NSString*) describeConnections {
NSMutableArray* connections = [NSMutableArray arrayWithCapacity:1000];
for (MIDINetworkConnection* connection in [[MIDINetworkSession defaultSession] connections]) {
[connections addObject:[[connection host] name]];
}
if ([connections count] > 0) {
return [connections componentsJoinedByString:#", "];
}
else
return #"(Not connected)";
}
When the app crashes it stops on the line
for (MIDINetworkConnection* connection in [[MIDINetworkSession defaultSession] connections])
The error I am getting is
Thread 1: EXC_BAD_ACCESS(code=EXC_1386_GPFLT)
In the debugger it shows
_impl _MIDINetworkConnectionImpl * NULL
I have tried to prevent the crashing by checking if MIDINetworkSession is NULL before looping through the connections but that hasn't worked. Occasionally when xcode crashes it will stop at
int main(int argc, char *argv[])
{
#autoreleasepool {
int retVal = UIApplicationMain(argc, argv, nil, nil);
return retVal;
}
}
Can anyone offer a guess as to what's happening?
It seems that connections contain NULL, in some case the system dealloc the connections.But in the set, it cannot use the NULL to be elements, so you should check the connections or use the try catch to get the exception.
Related
I'm learning objective-c manual memory management. I have the following example:
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSObject *o = [[NSObject alloc] init];
NSLog(#"%#", o);
[o release];
NSLog(#"%#", o);
}
return 0;
}
The output for this code is:
2015-07-31 16:18:34.694 test[2378:96008] <NSObject: 0x10020d110>
2015-07-31 16:18:34.696 test[2378:96008] <NSObject: 0x10020d110>
How is it possible, that after calling 'release' object is still present in memory (has the same address as before calling 'release') and NSLog does NOT give me EXC_BAD_ACCESS exception ?
That's because o still points to 0x10020d110, even after you've released the object.
Releasing an object does not change references to that object to nil, but they are invalid and if you attempted to send a message via the reference, undefined behaviour would ensue.
In your case, however it does not crash, as both NSLog() calls are calling [o description].
I'm having an issue opening my sqlite database for an iPhone app I'm writing. I thought I followed the tutorials verbatim but for some reason I am getting an "Out of memory" error.
-(NSString *) filepath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
return [[paths objectAtIndex:0] stringByAppendingPathComponent:#"db.sqlite"];
}
-(sqlite3*)openDB{
if(db == NULL){
sqlite3 *newDBConnection;
if(sqlite3_open([[self filepath] UTF8String], &newDBConnection) != SQLITE_OK){
sqlite3_close(db);
NSLog(#"%s SQL error '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(db), sqlite3_errcode(db));
db = NULL;
}
else{
NSLog(#"db opened");
}
}
return db;
}
DB is an ivar and I am calling db = [self openDB]; in the initialization method.
The sqlite3_open is failing because you are using NSDocumentationDirectory instead of NSDocumentDirectory.
The reason you're receiving the "Out of memory" error is that sqlite3_open is updating newDBConnection, but the sqlite3_errmsg is trying to use db (which is still NULL). And whenever you call sqlite3_errmsg with a NULL for the sqlite3 pointer, SQLite somewhat confusingly returns an "Out of memory" message.
Also note that even if you fix the two above issues, note that you are calling sqlite3_errmsg after performing sqlite3_close. Make sure to get your error message before you call sqlite3_close.
E.g. I would suggest:
- (BOOL)openDB {
if (db == NULL) {
int rc;
if ((rc = sqlite3_open([[self filepath] UTF8String], &db)) != SQLITE_OK) {
NSLog(#"%s SQL error '%s' (%d)", __FUNCTION__, sqlite3_errmsg(db), rc);
sqlite3_close(db);
db = NULL;
return false; // open failed
} else {
NSLog(#"db opened");
return true; // open successful
}
}
return true; // already open
}
Note, a minor point, given that sqlite3_open returns the error code, I would just save that directly, rather than calling sqlite3_errcode to get the code that was just returned.
I want to integrate in my iPad application a way to monitor the user activity and especially the exceptions that occurred and triggered the application to stop, something like the bug report of Apple but for the mobile clients.
I tried to encapsulate the main action (main.m) between #try and #catch blocks, but the exception is not thrown until there, and I just can't add such blocks everywhere in my code. Neither the delegate method applicationWillTerminate is not called, the application is just brutally stopped without any notification.
Any ideas on this ?
It works for me in main.m
int main(int argc, char *argv[]) {
#autoreleasepool {
int retVal = 0;
#try {
retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
#catch (NSException *exception) {
NSLog(#"Exception: %#", exception);
[exception raise];
}
return retVal;
}
}
P.S.
Another tricky way : EXC_BAD_ACCESS automatic handling
And example of NSUncaughtExceptionHandler
I am trying to make an iOS app without using xibs or storyboards. So my main.m
looks like this:
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
[pool release];
return retVal;
}
If I check value of [AppDelegate class] it is (null).
So the question is, why?
Also if i check [NSString class] or other class from standard library it performs normally.
I thought that file is not in Compile sources list, but it's there. This problem only occurs in one project.
Check if you have initialized assigned some controller to your window's root controller in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions.
Check out this answer.
I've noticed that there is a different way in Xcode 4.2 to start the main function:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([PlistAppDelegate class]));
}
}
and
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Does anybody know the difference between those two?
The first one is using ARC, which is implemented in iOS5 and above to handle memory management for you.
On the second one, you're managing your own memory and creating an autorelease pool to handle every autorelease that happens inside your main function.
So after reading a bit on what's new on Obj-C with iOS5 it appears that the:
#autoreleasepool {
//some code
}
works the same as
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// some code
[pool release];
with the difference that the last one would throw an error on ARC.
EDIT:
The first one is using ARC or not.