std::map initialization crashing on iPhone device, but not in simulator - iphone

I've tried turning on the Call C++ Default Ctors/Dtors in Objective-C flag but I'm still getting an EXC_BAD_ACCESS error when I first try to access my map:
(*[TextureBatcher getSharedTextureBatcher].getMap)[texID].vertexCount=0;
(*[TextureBatcher getSharedTextureBatcher].getMap)[texID].indexCount=0;
getMap just returns a reference to my map:
-(VertexMap *) getMap{
return &texMap;
}
And a VertexMap is a typedef of a std::map:
typedef std::map<GLuint, VertexInfo> VertexMap;
Not sure why this is failing on device and not in the simulator, any thoughts?

Just so we're clear:
(*[TextureBatcher getSharedTextureBatcher].getMap)[texID].vertexCount=0;
If theMap[texID] does not exist, the above line will cause a VertexInfo object to be constructed (with the default constructor, VertexInfo()). Is this what you're intending?
Perhaps the underlying std::map is implemented differently on the device, preventing this kind of initialisation?
Are you sure you set the Call C++ Default Ctors/Dtors in Objective-C flag on the Device target, not just the Simulator target?
Generally, the pattern is to use pointers here (C++) so you'd end up with:
typedef std::map<GLunit, VertexInfo*> VertexMap;
VertexMap theMap;
theMap[0] = new VertexInfo(...);
// now operate on theMap[0] normally
Or did I misunderstand the question?

Related

Why am I getting this warning from Xcode? The iOS code seems fine

This one has me stumped. I'm writing an iPhone app that tracks bus schedules. Users can bookmark their favorite bus stops so they can jump directly to them from the home screen. I manage the list of favorites in my AppDelegate class (unrelated code has been redacted):
#interface AppDelegate : NSObject <UIApplicationDelegate>
+ (BOOL) isInFavorites: (FavoriteStopData*) inStop;
#end
I have a view controller that presents the list of stops for a given bus route and lets users select one to see predicted bus arrival times for that stop in a new view (and maybe add the stop to their list of favorites):
#implementation RouteStopsViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
FavoriteStopData *stopData = [[FavoriteStopData alloc] init];
// ... set various properties in stopData from data in the selected cell
FavoriteStopViewController *fvc = [[FavoriteStopViewController alloc] initWithNibName:#"FavoriteStopViewController" bundle:nil];
fvc.stop = stopData;
fvc.isBookmarked = [AppDelegate isInFavorites:stopData];
[stopData release];
[self.navigationController pushViewController:fvc animated:YES];
[fvc release];
}
#end
The line
fvc.isBookmarked = [AppDelegate isInFavorites:stopData];
gets two warnings:
"'AppDelegate' may not respond to +isInFavorites:"
"Passing argument 1 of 'setIsBookmarked' makes integer from pointer without a cast"
I can't see any reason for Xcode to think '+isInFavorites:' is undefined, yet it does. I've verified that these possible causes for the warning are not in fact the case:
'+isInFavorites:' is declared in "AppDelegate.h" (as shown above)
"RouteStopsViewController.m" does #import "AppDelegate.h" (and "FavoriteStopData.h" and "FavoriteStopViewController.h")
'isBookmarked' is a public BOOL property on FavoriteStopViewController
The code is not being munged by some #define macro; when I preprocess "RouteStopsViewController.m", this code is unchanged.
The code behaves correctly, but I REALLY don't want to live with a warning that I must ignore every time the code compiles, and disabling this warning with some #pragma is a road I'd rather not take unless I have to.
I've tried renaming the method name, the variable names, using the method to set a local BOOL variable and then setting the property with that, using a conditional operator (x ? y : z) to make sure I'm passing a BOOL to the property ... nothing works. That first warning never goes away.
Can anyone suggest why Xcode is giving me this warning?
This is with Xcode 4.2 (Build 4C199) and iOS 5 SDK running in the 5.0 iPhone Simulator on a MacBook Pro running Mac OS X 10.6.8 (Snow Leopard).
If the +isInFavorites: method was completely unknown to the compiler then you'd see a warning like +isInFavorites: not found (return type defaults to 'id').
If you're not seeing that warning then we can assume that the compiler has seen a declaration of that method somewhere. However, the compiler expects this method to return a pointer rather than a BOOL, which is why you're seeing the makes integer from pointer without a cast warning.
Check for any other declarations of an isInFavorites: method in your project. Check for any global variables named AppDelegate that may conflict with your class name. Check for any circular imports between AppDelegate.h and RouteStopsViewController.h. Try renaming your AppDelegate class.
declare your isInFavorites method in your appdelegate.h file.
'AppDelegate' may not respond to +isInFavorites:
Passing argument 1 of 'setIsBookmarked' makes integer from pointer without a cast
The first error causes the second. The compiler's confusion on the existence of +isInFavorites: causes the compiler to assume the return type is id
This assumption causes the warning of making integer from pointer without a cast
You really have to focus on the first warning.
Are these the only warnings?
Try changing your AppDelegate.h to
#class FavoriteStopData
#interface AppDelegate : NSObject <UIApplicationDelegate>
+ (BOOL) isInFavorites: (FavoriteStopData*) inStop;
#end
If you still have issues, you might want to consider making this an instance method instead, considering the appDelegate is valid the whole runtime of your app
Found it. Even makes perfect sense ... now that I know exactly where to look.
My project has two targets: Dev for the version I use to test new code, and App for the user-facing version. Each has its own AppDelegate class (and some other duplicates). Code specific to one target or the other goes into either the ./Dev/ or the ./App/ folder. Common code goes into other folders.
Recently I promoted one Dev-specific class to be used in both targets ... but hadn't yet moved the files out of the Dev folder. This was my problematic RouteStopsViewController. My project was compiling the right "AppDelegate.m", but Xcode was finding the 'wrong' (to my thinking) "AppDelegate.h" because it was looking first in the same folder as "RouteStopsViewController.m".
The fix was easy: move RouteStopsViewController out of the Dev-specific folder into one for code shared by both targets. Now Xcode uses the "AppDelegate.m" file it's compiling to find the matching "AppDelegate.h".
I knew at the time I should move that RouteStopsViewController class when I decided to reuse it in the App target, I just didn't get around to it. When it comes to writing code, trust your nose. If it smells funny, it very probably is.

Should get 20 errors... but get 0... when compiling without declaring an instance variable

In my iPhone apps I regularly do this in xCode v3.2.3:
Declare a BOOL variable in the *.h file
Use #property in the same *.h file.
Use #sythesize in the matching *.m file.
I accidentally forgot to do #1... but it still complied fine. 0 warnings. 0 errors. 0 analyzer errors.
How can that be? Shouldn't my code to loaded with compiler-errors everywhere that variable is trying to be used?
This is a feature of the new runtime. See this question for more details.
Automatic synthesis of instance variables (ivars) is a feature of the Objective-C 2.0 runtime on OS X and of the new iOS Objective-C runtime. The #synthesize directive will automatically create the necessary ivar at runtime unless you have declared it yourself. This is made possible by Objective-C 2.0's non-fragile ivar support. Thus, there is no error and you should not receive them.
Ultimately, it's a good thing that you don't have to declare ivars in the interface of a class. They are (probably) implementation-specific details which you don't want to have visible as part of the public interface of the class. Note that using class categories you can also automatically synthesize ivars for "private" properties as well.

Objective-C, properties for references

This might be iPhone specific, I'm not sure. The compiler doesn't complain when building for the simulator but when compiling for device it throws some funky errors when I try to set properties for references to objects. Eg,
#property (nonatomic) CGRect &finalFrame;
and the coressponding synthesizer
#synthesize finalFrame;
for a variable declared as
CGRect finalFrame;
Gives the errors
type of property 'finalFrame' does not match type of ivar 'finalFrame'
Unrecognisable insn:
Internal compiler error: Bus error
Internal compiler error: in extract_insn, at recog.c:2904
However I can do it manually without issue, with the following methods:
- (CGRect&)finalFrame;
- (void)setFinalFrame:(CGRect&)aFrame;
Is this a gcc bug? It does compile for the simulator.
Your property is declared as a reference type (CGRect&) but your instance variable is not a reference type (CGRect). They need to be the same to use #synthesize.
Also, it's a little weird to be using C++ reference types as Objective-C properties, but I guess that might work as long as all the files are being compiled as Objective-C++.

NSStringFromPoint disappears under Objective-C++

The function NSStringFromPoint disappears when I compile my code using objective-C++, but it's fine under objective-C.
How can I make objective-C++ see that function?
If I compile under Objective-C++ it says:
error: 'NSStringFromPoint' was not declared in this scope
error: 'NSStringFromRect' was not declared in this scope
error: 'NSEqualSizes' was not declared in this scope
Someone can correct me if I'm wrong, but if you're linking against the iPhone SDK, there is no NSPoint or NSStringFromPoint. UIKit uses the Core Graphics structs CGPoint, CGSize and CGRect. The equivalent function would be NSStringFromCGPoint.
The Simulator libraries do not quite match up with the iPhone libraries -- I'm fairly certain applications compiled for the simulator link against the Mac's own Foundation.framework. For example, I wasted a lot of time in the pre-2.0 days thinking that NSXMLDocument was available on iPhone because it compiled and ran in the simulator.
I compiled this simple application:
#include <Cocoa/Cocoa.h>
int main (void)
{
NSLog (#"%#", NSStringFromPoint(NSMakePoint(10, 10));
return 0;
}
Using this command line:
gcc -x objective-c++ test.mm -framework Cocoa -lstdc++
And I got this output (ignoring the error about no autorelease pool in place):
2010-05-12 12:41:33.946 a.out[290:10b] {10, 10}
Make sure you're including the right headers, at the very least, make sure you're importing <Foundation/Foundation.h>. An explicit #import <Foundation/Foundation.h> will do no harm if it has already been included.

iPhone app running in Instruments fails with unrecognized selector

I have an app that appears to run without problems in normal use. The Clang Static Analyzer reports no problems either. When I try to run it in Instruments, it fails with an unrecognized selector exception.
The offending line is a simple property setter of the form:
self.bar = baz;
To figure out what's going on, I added an NSLog() call immediately above it:
NSLog(#"class = %# responds = %d", [self class], [self respondsToSelector:#selector(setBar:)]);
self.bar = baz;
On the emulator (without Instruments) and on a device, this shows exactly what I'd expect:
class = Foo responds = 1
When running under Instruments, I get:
class = Foo responds = 0
I'm stumped as to what could cause this. Perhaps a different memory location is getting tromped on when it's in the Instruments environment? Can anyone suggest how I might debug this?
If bar belongs to self, can't you do bar=baz; ?
Check your properties.
Perhaps to you need a cast on baz?
There's not enough information here to know what's going on, but then, if you knew what information to provide you'd probably have already fixed it. So. A few things to check:
Is the "self" pointer being swizzled in any way? Try printing out the value of self at various points just for sanity's sake
When your code runs in Instruments, is it running in a different mode? (32-bit vs. 64-bit, Garbage collected vs. Retain-Release, etc.) I'm not sure why any of those would have an effect, but if it's running in a different mode, that's something to look into.
Are you synthesizing the setter correctly? Or is it being provided dynamically (via Core Data, etc.)? If you manually specify a setBar: method, do you still get the error?