6

When I call NSLog from C++, Xcode complains that the format string passed to NSLog is not a literal string. Here's a line of code that triggers the warning:

NSLog(CFSTR("Leaking?"));

I'm not aware of any way to code a literal NSString in C++, and I don't see a relevant warning I can turn off in the project settings. Is there a way to call NSLog from C++ without triggering this message? I'm using Xcode 4.2.1.

Edit: This really is C++ code. I usually avoid Objective-C++, sticking to either Objective-C or plain old C++, because there's no official documentation about what works in Objective-C++ and what doesn't. I've only found vague warnings that (for example) there may be issues with some parts of the STL. I use templates, the STL, and other "advanced" features of C++, so I want to play it safe.

Edit #2, the solution: I just figured out clang supports a lot more warning flags than are actually documented. (It should have been obvious from the long list of warnings that Xcode offered me.) I tried -Wno-format-nonliteral a la gcc, and now Xcode is happy.

dkh
  • 185
  • 1
  • 2
  • 8
  • 2
    If you are calling `NSLog`, which is part of Foundation, then you are using Objective-C. Use `@"Leaking?"` and make sure your file has a `.mm` extension. – Joe Mar 20 '12 at 19:01
  • @Joe ... unless he means Objective-C++ ? – csl Mar 20 '12 at 19:07
  • 1
    @csl I moved the comment to an answer with some clarification. – Joe Mar 20 '12 at 19:09

2 Answers2

7

All you have to do is write @"this" to create a literal NSString object.

So replace that line with NSLog(@"Leaking?"); and you should be fine.

You might have to rename your file with the extension .mm to make sure it is compiled as Objective-C++ (the mutant love-child of Objective-C and C++). If you don't want to do that, you could make a wrapper function in a tiny mm file that calls NSLog, and then call that function from your C++ code. It would look like this:

void MyNSLog(const char *message)
{
    NSLog(@"%s", message);
}

Note that the reason the compiler is giving you grief is that using anything but an immutable string literal (where the contents are known at compile time) is a security risk. Otherwise, the format string could be changed to include format specifiers (e.g., %d) for parameters that aren't there. If that happened, NSLog would just get random pointers from the stack and something bad could happen. (See this question for more info.)

Community
  • 1
  • 1
benzado
  • 82,288
  • 22
  • 110
  • 138
  • +1 for the suggestion to define a helper function in a separate .mm file. I didn't use it this time, but I'm sure it's going to come in handy in the future, since I'm generally cautious about using Objective-C++. – dkh Mar 20 '12 at 19:33
4

If you are calling NSLog, which is part of Foundation, then you are using Objective-C. Use NSLog(@"Leaking?"); and make sure your file has a .mm extension to make it clear that you are mixing Objective-C and C++.

Joe
  • 56,979
  • 9
  • 128
  • 135
  • Just to clarify, I'm confused. Why not just name this a `.m` extension instead of `.mm`, if Foundation is Objective-C? Did you mean to say that NSLog is Objective C++ instead, or am I confused? Thanks! – jamesmortensen Sep 06 '12 at 21:16
  • 1
    I was speculating that maybe `NSLog` was getting called from a `.cpp` file which would not work because `NSLog` is only `Objective-C`. And to mix `Objective-C` and `C++` the extension [should be `.mm`](http://stackoverflow.com/questions/7727249/calling-c-function-from-objective-c-class/7727308#7727308). – Joe Sep 06 '12 at 21:19