Вызов NSLog из C ++: строка формата не является строковым литералом (потенциально небезопасно)

Когда я вызываю NSLog из C ++, Xcode жалуется, что строка формата, переданная в NSLog, не является буквальной строкой. Вот строка кода, которая вызывает предупреждение:

NSLog(CFSTR("Leaking?"));

Мне неизвестен способ кодирования буквального NSString на C ++, и я не вижу соответствующего предупреждения, которое можно отключить в настройках проекта. Есть ли способ вызвать NSLog из C ++, не вызывая это сообщение? Я использую Xcode 4.2.1.

Изменить: это действительно код C ++. Я обычно избегаю Objective-C ++, придерживаясь Objective-C или простого старого C ++, потому что нет официальной документации о том, что работает в Objective-C ++, а что нет. Я нашел только расплывчатые предупреждения о том, что (например) могут быть проблемы с некоторыми частями STL. Я использую шаблоны, STL и другие «продвинутые» функции C ++, поэтому хочу перестраховаться.

Отредактируйте №2, решение: я только что понял, что clang поддерживает намного больше предупреждающих флагов, чем фактически задокументировано. (Это должно было быть очевидно из длинного списка предупреждений, которые предлагал мне Xcode.) Я попробовал -Wno-format-nonliteral a la gcc, и теперь Xcode доволен.


person dkh    schedule 20.03.2012    source источник
comment
Если вы вызываете NSLog, который является частью Foundation, значит, вы используете Objective-C. Используйте @"Leaking?" и убедитесь, что ваш файл имеет расширение .mm.   -  person Joe    schedule 20.03.2012
comment
@ Джо ... разве он имеет в виду Objective-C ++?   -  person csl    schedule 20.03.2012
comment
@csl Я переместил комментарий к ответу с некоторыми пояснениями.   -  person Joe    schedule 20.03.2012


Ответы (2)


Все, что вам нужно сделать, это написать @"this", чтобы создать буквальный объект NSString.

Так что замените эту строку на NSLog(@"Leaking?");, и все будет в порядке.

Возможно, вам придется переименовать свой файл с расширением .mm, чтобы убедиться, что он скомпилирован как Objective-C ++ (мутантный ребенок любви Objective-C и C ++). Если вы не хотите этого делать, вы можете создать функцию-оболочку в крошечном mm-файле, который вызывает NSLog, а затем вызывать эту функцию из вашего кода C ++. Это выглядело бы так:

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

Обратите внимание, что компилятор огорчает вас тем, что использование чего-либо, кроме неизменяемого строкового литерала (содержание которого известно во время компиляции), представляет собой угрозу безопасности. В противном случае строку формата можно изменить, чтобы включить спецификаторы формата (например, %d) для параметров, которых нет. Если это произойдет, NSLog просто получит случайные указатели из стека, и может случиться что-то плохое. (См. этот вопрос для получения дополнительной информации. )

person benzado    schedule 20.03.2012
comment
+1 за предложение определить вспомогательную функцию в отдельном файле .mm. В этот раз я не использовал его, но уверен, что он пригодится в будущем, поскольку я обычно осторожно отношусь к использованию Objective-C ++. - person dkh; 20.03.2012

Если вы вызываете NSLog, который является частью Foundation, то вы используете Objective-C. Используйте NSLog(@"Leaking?"); и убедитесь, что ваш файл имеет расширение .mm, чтобы было ясно, что вы смешиваете Objective-C и C++.

person Joe    schedule 20.03.2012
comment
Просто чтобы прояснить, я запутался. Почему бы просто не назвать это расширение .m вместо .mm, если Foundation является Objective-C? Вы хотели сказать, что NSLog - это Objective C ++, или я запутался? Спасибо! - person jmort253; 07.09.2012
comment
Я предполагал, что, возможно, NSLog был вызван из .cpp файла, который не работал, потому что NSLog - это всего лишь Objective-C. А для смешивания Objective-C и C++ расширение должно быть _7 _. - person Joe; 07.09.2012