os_log timeval格式的Clang错误

时间:2017-04-16 12:23:47

标签: ios objective-c logging clang

我第一次使用Apple的Unified Logging,并取得了一些成功。但是,我无法使用建议的%{timeval}.*P自定义格式说明符。

我的第一次尝试是:

struct timeval some_time;
// ... populate `some_time` 
os_log_info(OS_LOG_DEFAULT, "a thing happened at %{timeval}.*P", some_time);

但clang报告错误:field precision should have type 'int', but argument has type 'struct timeval'

我认为问题在于clang并不理解os_log格式规则,如果我能解决如何让clang通过clang diagnostic push等来抑制错误, 我会。看起来基础宏OS_LOG_CALL_WITH_FORMAT似乎试图做到这一点,没有运气。

我是否滥用timeval格式说明符?

这是Xcode 8.3.1,我还没有尝试过早期版本的Xcode。

2 个答案:

答案 0 :(得分:1)

根据documentationtimeval格式说明符是正确的。显然,从Xcode 8.3.2开始,Clang还没有意识到这些新的格式字符串。通过#clang diagnostic ignored "-Wformat"停用它将是徒劳的尝试。

Format specifier documentation

显然没有解决方案 - 同时避免使用这些新的花式格式说明符。具体来说,请避免使用以.*P结尾的格式字符串。但是d格式似乎有效。

答案 1 :(得分:1)

<强> TL; DR

工作代码

os_log_info(OS_LOG_DEFAULT, "a thing happened at %{timeval}.16P", &some_time);

OR

os_log_info(OS_LOG_DEFAULT, "a thing happened at %{timeval}.*P", (int)sizeof(some_time), &some_time);

这里的问题是格式定义中的通配符(*)代表int。所以事实上%{timeval}。* P接受2个参数:int和指向timeval struct的指针。

不幸的是,这是非常糟糕的文档,甚至os_log使用的Apple Sample Code都没有这方面的例子。

到目前为止,查看示例的最佳方法是查看LLVM源代码中的测试。 format-strings-oslog.m

__builtin_os_log_format(buf, "%d", i);
__builtin_os_log_format(buf, "%P", p); // expected-warning {{using '%P' format specifier without precision}}
__builtin_os_log_format(buf, "%.10P", p);
__builtin_os_log_format(buf, "%.*P", p); // expected-warning {{field precision should have type 'int', but argument has type 'void *'}}
__builtin_os_log_format(buf, "%.*P", i, p);
__builtin_os_log_format(buf, "%.*P", i, i); // expected-warning {{format specifies type 'void *' but the argument has type 'int'}}