sscanf 在 iPhone OS 3.1.2 上是线程安全的吗?
当我最终意识到问题是从多个线程调用 sscanf 时,我只是花了一整天的时间调试一个随机错误。
我通过运行以下代码进行确认,该代码在 Snow Leopard 上按预期工作,但在操作系统 3.1.2 的 iphone 上产生非常奇怪的结果。它在模拟器中也运行良好。
在 iPhone 上,解析的数字将是字符串中使用的数字的随机组合。
如果有人可以检查这是否是一个普遍问题或者是否是我这边的错误,那将非常有帮助。
- (void)testIt
{
[NSThread detachNewThreadSelector:@selector(scanfTest) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(scanfTest) toTarget:self withObject:nil];
}
- (void)scanfTest
{
while (true)
{
float value = 0.0f;
sscanf("456", "%f", &value);
sscanf( "1.63", "%f", &value);
if (value != 1.63f)
NSLog(@"strange value is %f", value);
}
}
我做了一些进一步的检查,看来只有浮点数才是问题。
此代码有效
- (void)scanfTest4
{
while (true)
{
int year = 0;
int month = 0;
int day = 0;
sscanf("20090131", "%4d%2d%2d", &year, &month, &day);
sscanf("19840715", "%4d%2d%2d", &year, &month, &day);
if (year != 1984 || month != 7 || day != 15)
NSLog(@"bla");
}
}
,此代码因相同的随机数字问题而失败
- (void)scanfTest4
{
while (true)
{
int year = 0;
int month = 0;
float day = 0.0f;
sscanf("20090131", "%4d%2d%2f", &year, &month, &day);
sscanf("19840715", "%4d%2d%2f", &year, &month, &day);
if (year != 1984 || month != 7 || day != 15.0f)
NSLog(@"bla");
}
}
I was just spending my whole day debugging a random bug when i finally realized the Problem was sscanf being called from multiple threads.
I confirmed by running the following code which works as expected on Snow Leopard but produces very strange results on my iphone with os 3.1.2. It also works fine in the Simulator.
On the iPhone the parsed number will be a somewhat random combination of the digits used in the strings.
It would be very helpfull if anyone could check if this is a general Problem or if it's a mistake on my side.
- (void)testIt
{
[NSThread detachNewThreadSelector:@selector(scanfTest) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(scanfTest) toTarget:self withObject:nil];
}
- (void)scanfTest
{
while (true)
{
float value = 0.0f;
sscanf("456", "%f", &value);
sscanf( "1.63", "%f", &value);
if (value != 1.63f)
NSLog(@"strange value is %f", value);
}
}
I did some further checking and it appears only floating point numbers are an issue.
This code works
- (void)scanfTest4
{
while (true)
{
int year = 0;
int month = 0;
int day = 0;
sscanf("20090131", "%4d%2d%2d", &year, &month, &day);
sscanf("19840715", "%4d%2d%2d", &year, &month, &day);
if (year != 1984 || month != 7 || day != 15)
NSLog(@"bla");
}
}
And this code fails with the same random digit issues
- (void)scanfTest4
{
while (true)
{
int year = 0;
int month = 0;
float day = 0.0f;
sscanf("20090131", "%4d%2d%2f", &year, &month, &day);
sscanf("19840715", "%4d%2d%2f", &year, &month, &day);
if (year != 1984 || month != 7 || day != 15.0f)
NSLog(@"bla");
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
SUSv2 说(线程):
sscanf()
不在不需要线程安全的接口列表中。这并不是说 iPhone 符合 SUSv2 标准,但我认为它至少解释了为什么您的代码应该在 Snow Leopard 上运行。另外,我手头没有更新的 POSIX 规范,因此我假设它自 1997 年以来就没有发生过变化,这有点冒险。
SUSv2 says (Threads):
sscanf()
is not on the list of interfaces which need not be thread-safe.This is not to say that the iPhone is SUSv2-compliant, but I think at least it explains why your code should be expected to work on Snow Leopard. Also I don't have a more recent POSIX spec to hand, so I'm taking a bit of a risk in assuming it hasn't changed since 1997.
sscanf 不是线程安全的。它是在线程存在之前编写的,其设计要求它使用内部静态临时变量。 sprintf 也是如此。
我的情况是, sscanf 无论如何都太过分了。只需使用
atof
即可。sscanf is not thread safe PERIOD. it was written before threads existed its design requires it to use internal static temp variables. the same is true for sprintf.
I your case, sscanf is overkill anyway. just use
atof
instead.谢谢约翰和斯蒂芬!
我可以确认 atof 和 strtof 在这种情况下都可以安全使用。
Thank you John and Stephen!
I can confirm that both atof and strtof are safe to use in this situation.
如果我可能会问,当您可以使用 NSString 数字转换时,为什么需要使用 sscanf/atof ?
If I may ask, why do you need to use sscanf/atof when you can use the NSString numeric conversions?