15000 次迭代后,出现“错误:无法分配区域”——无内存警告
要点:使用ARC; 完整错误是:
malloc: * mmap(size=2097152) 失败(错误代码=12) 错误:无法分配区域 ** 在malloc_error_break中设置断点进行调试
四次。
该问题的唯一实质代码是:
-(void)iterate:(NSString *)string{
frontString = NULL;
backString = NULL;
arrayOfNumbers = NULL;
backwardArrayOfNumbers = NULL;
nextString = NULL;
nextArrayOfNumbers = NULL;
nextArrayOfNumbers = [NSMutableArray new];
nextString = [NSMutableString new];
backwardArrayOfNumbers = [NSMutableArray new];
arrayOfNumbers = [NSMutableArray new];
frontString = [[NSMutableString alloc] initWithString:string];
backString = [NSMutableString new];
if (string.length > 1) {
iteration++;
for (unsigned long i = 0; i < string.length; ++i) {
NSString *sub = [string substringWithRange:(NSRange){i, 1}];
[arrayOfNumbers addObject:sub];
NSString *back = [string substringWithRange:(NSRange){string.length-(i+1), 1}];
[backwardArrayOfNumbers addObject:back];
[backString appendString:back];
sub = NULL;
back = NULL;
}
if ([frontString isEqualToString:backString]) {
[palindromicNumberTextView setText:string];
[iterationLabel setText:[NSString stringWithFormat:@"%ld", iteration]];
} else {
int carrier = 0;
for (long long j = arrayOfNumbers.count-1; j > -1; --j) {
int a = [[arrayOfNumbers objectAtIndex:j] intValue];
int b = [[backwardArrayOfNumbers objectAtIndex:j] intValue];
//NSLog(@"a = %i, b = %i", a, b);
int c = a+b+carrier;
if (c > 9) {
c = c-10;
carrier = 1;
} else {
carrier = 0;
}
[nextArrayOfNumbers addObject:[NSString stringWithFormat:@"%i", c]];
if (carrier == 1 && (nextArrayOfNumbers.count == arrayOfNumbers.count)) {
[nextArrayOfNumbers addObject:[NSString stringWithFormat:@"%i", carrier]];
}
//NSLog(@"nextArrayOfNumbers = %@", nextArrayOfNumbers);
}
for (int i = 0; i < nextArrayOfNumbers.count; ++i) {
NSString *back = [nextArrayOfNumbers objectAtIndex: nextArrayOfNumbers.count-(i+1)];
//NSLog(@"back = %@", back);
[nextString appendString:back];
back = NULL;
}
if (iteration%1000 == 0) {
NSLog(@"iteration %ld; count:%u", iteration, nextArrayOfNumbers.count);
}
//NSLog(@"iteration %ld", iteration);
[self iterate:nextString];
}
}
}
15,000+次迭代后,崩溃+错误,没有内存警告:
- (void)didReceiveMemoryWarning
{
NSLog(@"Error near iteration %ld", iteration);
[super didReceiveMemoryWarning];
}
知道问题可能是什么吗?提前致谢!
编辑:在 CString
和 NSString
之间进行转换对于 ARC 来说是一件痛苦的事情。因此,我在循环内使用了 @autoreleasepool{}
(以及 nil
而不是 NULL
),这大大减少了内存使用量。我已经进行了超过 50k 次迭代。
Points: Using ARC;
full error is:
malloc: * mmap(size=2097152) failed (error code=12)
error: can't allocate region
** set a breakpoint in malloc_error_break to debug
four times.
The only code of any substance to the question is:
-(void)iterate:(NSString *)string{
frontString = NULL;
backString = NULL;
arrayOfNumbers = NULL;
backwardArrayOfNumbers = NULL;
nextString = NULL;
nextArrayOfNumbers = NULL;
nextArrayOfNumbers = [NSMutableArray new];
nextString = [NSMutableString new];
backwardArrayOfNumbers = [NSMutableArray new];
arrayOfNumbers = [NSMutableArray new];
frontString = [[NSMutableString alloc] initWithString:string];
backString = [NSMutableString new];
if (string.length > 1) {
iteration++;
for (unsigned long i = 0; i < string.length; ++i) {
NSString *sub = [string substringWithRange:(NSRange){i, 1}];
[arrayOfNumbers addObject:sub];
NSString *back = [string substringWithRange:(NSRange){string.length-(i+1), 1}];
[backwardArrayOfNumbers addObject:back];
[backString appendString:back];
sub = NULL;
back = NULL;
}
if ([frontString isEqualToString:backString]) {
[palindromicNumberTextView setText:string];
[iterationLabel setText:[NSString stringWithFormat:@"%ld", iteration]];
} else {
int carrier = 0;
for (long long j = arrayOfNumbers.count-1; j > -1; --j) {
int a = [[arrayOfNumbers objectAtIndex:j] intValue];
int b = [[backwardArrayOfNumbers objectAtIndex:j] intValue];
//NSLog(@"a = %i, b = %i", a, b);
int c = a+b+carrier;
if (c > 9) {
c = c-10;
carrier = 1;
} else {
carrier = 0;
}
[nextArrayOfNumbers addObject:[NSString stringWithFormat:@"%i", c]];
if (carrier == 1 && (nextArrayOfNumbers.count == arrayOfNumbers.count)) {
[nextArrayOfNumbers addObject:[NSString stringWithFormat:@"%i", carrier]];
}
//NSLog(@"nextArrayOfNumbers = %@", nextArrayOfNumbers);
}
for (int i = 0; i < nextArrayOfNumbers.count; ++i) {
NSString *back = [nextArrayOfNumbers objectAtIndex: nextArrayOfNumbers.count-(i+1)];
//NSLog(@"back = %@", back);
[nextString appendString:back];
back = NULL;
}
if (iteration%1000 == 0) {
NSLog(@"iteration %ld; count:%u", iteration, nextArrayOfNumbers.count);
}
//NSLog(@"iteration %ld", iteration);
[self iterate:nextString];
}
}
}
15,000+ iterations later, crash + error, with no memory warning:
- (void)didReceiveMemoryWarning
{
NSLog(@"Error near iteration %ld", iteration);
[super didReceiveMemoryWarning];
}
Any ideas what the problem might be? Thanks in advance!
EDIT: Converting between CString
and NSString
is a pain with ARC. So I went with @autoreleasepool{}
inside the loops (and nil
rather than NULL
) and that has dramatically reduced memory usage. I'm up over 50k iterations.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
因此,如果程序使用那么多内存,它本身就会出现一些问题——您可以显着减少该算法的内存使用量。
无论如何,如果这发生在主线程上,您将不会收到内存警告。内存警告是在主线程上发出的,并且您没有机会处理该警告,因为您在主线程的运行循环有另一次机会执行其常规工作(例如处理内存警告或处理其他事件)之前就耗尽了内存。
如果这发生在辅助线程上,也许您会看到不同的情况,但这并不能解决问题的根源。
So the program itself has some issues if it's using that much memory -- you can reduce memory usage of this algo significantly.
Anyways, you won't get a memory warning if this takes place on the main thread. The memory warning is made on the main thread, and you give it no chance to handle the warning because you exhaust memory before the main thread's run loop has another chance to do its usual work (such as handle memory warnings or handle other events).
Perhaps you would see something different if this happened on a secondary thread, but that would not solve the root of the problem.
您正在递归地解决一个填满内存的问题。
您的计算机必须跟踪每次完成 15,000 个周期后的去向。这可能会变成很大的空间。
如果可以使此“尾递归”,则可以节省空间。例如:
//
You are solving a problem recursively which fills up memory.
Your computer has to keep track of where to go when it finishes each of 15,000 cycles. That can become a lot of space.
If it is possible to make this "tail recursive" you could save space. For instance:
//