gpt4 book ai didi

objective-c - 奇怪的数据最终出现在用户的XML保存文件中

转载 作者:搜寻专家 更新时间:2023-10-30 19:42:55 25 4
gpt4 key购买 nike

我的应用程序使用XML将用户数据保存到文件中。我刚刚收到两份来自用户的报告,他们在他们的文件中看到了完全出乎意料的数据。它不是XML,而是如下所示:

({"windows":[{"tabs":[{"entries":[{"url":"https://mail.google.com/a/cast...

文件的中间部分,重约30kb:
{\"n\":\"bc\",\"a\":[null]},{\"n\":\"p\",\"a\":[\"ghead\",\"\",0]},{\"n\":\"ph\",\"a\":[{\"gb_1\":\"http://www.google.com/

有谁能告诉我这是什么样的数据,或者它是如何在我的用户的数据文件中结束的?两位用户都报告说必须按住电源按钮关闭他们的机器。关闭一个是Firefox冻结,另一个是鼠标问题。其中一个用户实际上经历了内核恐慌。
我还不相信这是一个内存管理问题,因为我的用户基数超过100000人,而我只收到2份报告。我觉得它比较窄/稀有。
这是我用来将数据写入文件的代码:
NSString *xmlString = [[self convertContextToXmlString:context] retain];

NSError *e = nil;

[[xmlString dataUsingEncoding:NSUTF8StringEncoding] writeToFile:location options:NSDataWritingAtomic error:&e];
[xmlString release];
if (e) {
NSLog(@"An error occurred saving: %@", [e description]);
}
return e;

数据保存从不发生在后台线程上,总是发生在ui线程上。另外,我使用 NSDataWritingAtomic选项将数据写入文件。
编辑:第二个用户的文件有几乎相同的数据。所以两个错误的内容来自同一个地方,但是在哪里?我会尽快给这个问题加分200分。
AV/////wEAAAAAAAAAAAABAAA="}]}]},{"url":"http://googleads.g.doubleclick.net/pagead/ads?client=ca-pu

编辑2:收到用户的第三个报告,用户在按下电源按钮关闭机器后也经历了数据损坏。他的数据一开始有很多随机的垃圾,然后在最后有适当的数据:
(garbage)rred="1"><rest of it was normal xml...>

最佳答案

从一个苹果开发人员那里得到了很好的回答。将在未来几周将我现有的模型移植到核心数据中。(StAdOpSoad与一些列表/格式化相混淆,但在很大程度上仍然是可读的。)
我将以一个关于hfs加日志的词开始我的回答。自从在Mac OS X 10.2 .x中引入日志以来,Mac OS X的文件系统正确性保证一直是——不管内核恐慌、电源故障等等——文件系统操作将导致两种结果之一:
任何一个操作都将由日志向前滚动,在这种情况下,就好像操作已经成功完成一样。
或操作将被回滚,在这种情况下,就好像操作从未发生过一样。
此保证有两个关键限制:
o它适用于单个文件系统操作(创建、删除、移动等),而不是操作组。
o它只适用于逻辑文件系统结构,而不适用于文件中的数据。
简而言之,日志的目的是防止整个文件系统的损坏,而不是特定文件的损坏。
记住这一点,让我们看看-[nsdata writetofile:options:error:]的行为。它的行为可能非常复杂,但在典型情况下非常简单。探索这一点的一种方法是编写一些代码并使用查看其文件系统行为。例如,下面是一些测试代码:

- (IBAction)testAction:(id)sender
{

BOOL success;
NSData * d;
struct stat sb;

d = [@"Hello Cruel World!" dataUsingEncoding:NSUTF8StringEncoding];
assert(d != nil);

(void) stat("/foo", &sb);
success = [d writeToFile:@"/tmp/WriteTest.txt" options:NSDataWritingAtomic error:NULL];
(void) stat("/foo", &sb);
assert(success);
}

这两个调用仅仅是标记;它们可以很容易地看到哪些文件系统操作是由-WrreEtFoFILE生成的:选项:错误:。
您可以使用以下方法查看文件系统行为:
$sudo fs_用法-f filesys-w writetest
其中“writetest”是我的测试程序的名称。
以下是从生成的fs_使用情况输出中提取的内容:
14:33:10.317状态[2]/foo
14:33:10.317 lstat64 private/tmp/writetest.txt
14:33:10.317打开f=5(rwc\u e)专用/tmp/.dat2f56.000
14:33:10.317写入f=5 b=0x12
14:33:10.317同步f=5
14:33:10.317关闭f=5
14:33:10.318重命名private/tmp/.dat2f56.000
14:33:10.318 chmod私有/tmp/writetest.txt
14:33:10.318状态[2]/foo
您可以清楚地看到环绕“-WruteToFiels:选项”:“错误:调用”的“STAT”调用,这意味着这些调用之间的所有内容都是由-WrreTeFoFILE生成的:选项:错误:。
它是做什么的?其实很简单:
它创建、写入、FSycS并关闭包含数据的临时文件。
它将重命名您要写入的文件顶部的临时文件。
它重置最终文件的权限。
总之,这是一个非常标准的UNIX风格的安全保存。但问题是,这对数据完整性有何影响?需要注意的是,fsync不保证在返回之前将所有数据推送到磁盘。这个问题有一个漫长而复杂的历史,但总结是FSYNC被称为方式太多次,在太多的性能敏感的位置,为它作出这样的保证。这意味着,您看到的所有文件损坏问题都可能出现,如下所述:
“IPRORASTITENATOBADY2. IPR”和“IPRORASTITENATA BADY3.IPR”只是包含错误的数据。这可能发生如下情况:
应用程序创建临时文件。
应用程序写入临时文件。对此,内核:
a.在磁盘上分配一组块
b.将它们添加到文件中
c.扩展文件的长度
d.复制写入缓冲缓存的数据
应用fsyncs并关闭文件。内核通过调度要尽快写入的数据块作出响应。
应用程序在实际文件的顶部重命名临时文件。
系统内核崩溃。
当系统重新启动时,步骤1、2a..2c、3和4中的更改将从日志中恢复,这意味着您有一个包含无效数据的有效文件。
“IPRORASTIATEA BADY1. IPR”只是上面的细微变化。如果你用十六进制编辑器打开文件,你会发现它看起来不错,除了偏移量0x6000..0x61ff处的数据范围,它似乎包含了与你的应用完全无关的数据。值得注意的是,这个数据的长度0x200字节正好是一个磁盘块。因此,内核似乎成功地将除这一块之外的所有用户数据写入磁盘。
所以这会把你留在哪里?[NStaseRealToFiel:Value:Errist::]不太可能变得比以前更健壮;正如我之前提到的,这样的变化往往会对整个系统性能产生负面影响。这意味着你的应用程序将不得不处理这个问题。
在这方面,有三种常用方法可以强化应用程序:
a.f_fullfsync——您可以通过使用f_fullfsync选择器调用将文件提交到永久存储。您可以在应用程序中使用此功能,方法是将-[nsdata writetofile:options:error:]替换为您自己的代码,该代码调用f_fullfsync而不是fsync。
这种方法最明显的缺点是f_fullfsync非常慢。
日志——采用更健壮的文件格式的另一种选择,也许支持日志。sqlite就是一个很好的例子,您可以直接使用它,也可以通过核心数据使用它。
更安全的保存——最后,您可以通过备份文件实现更安全的保存机制。在调用-[nsdata write to file:options:error:]写入文件之前,您可以将以前的文件重命名为其他名称,并保留该文件以备不时之需。如果打开主文件,发现它已损坏,那么您将自动恢复到备份。
在这些方法中,我更喜欢b,特别是使用核心数据的方法b,因为核心数据提供了比数据完整性更大的好处。不过,对于快速修复选项c可能是您的最佳选择。
如果你对这件事有任何疑问,请告诉我。

关于objective-c - 奇怪的数据最终出现在用户的XML保存文件中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5224238/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com