Iphone CFAttributedStringSetAttribute和NSNumber中的EXC\u错误\u访问?
在我正在开发的一个objective c应用程序中,我遇到了一个令人恼火的EXC_BAD_访问错误。如果您能提供任何帮助,我们将不胜感激。我尝试了针对此错误的常规调试方法(打开NSZombieEnabled,检查retain/release/autorelease以确保我没有尝试访问解除分配的对象,等等),但似乎没有任何帮助 基本上,错误总是发生在该函数中:Iphone CFAttributedStringSetAttribute和NSNumber中的EXC\u错误\u访问?,iphone,objective-c,exc-bad-access,Iphone,Objective C,Exc Bad Access,在我正在开发的一个objective c应用程序中,我遇到了一个令人恼火的EXC_BAD_访问错误。如果您能提供任何帮助,我们将不胜感激。我尝试了针对此错误的常规调试方法(打开NSZombieEnabled,检查retain/release/autorelease以确保我没有尝试访问解除分配的对象,等等),但似乎没有任何帮助 基本上,错误总是发生在该函数中: void op_TJ(CGPDFScannerRef scanner, void *info) { PDFPage *self =
void op_TJ(CGPDFScannerRef scanner, void *info)
{
PDFPage *self = info;
CGPDFArrayRef array;
NSMutableString *tempString = [NSMutableString stringWithCapacity:1];
NSMutableArray *kernArray = [[NSMutableArray alloc] initWithCapacity:1];
if(!CGPDFScannerPopArray(scanner, &array)) {
[kernArray release];
return;
}
for(size_t n = 0; n < CGPDFArrayGetCount(array); n += 2)
{
if(n >= CGPDFArrayGetCount(array))
continue;
CGPDFStringRef pdfString;
// if we get a PDF string
if (CGPDFArrayGetString(array, n, &pdfString))
{
//get the actual string
const unsigned char *charstring = CGPDFStringGetBytePtr(pdfString);
//add this string to our temp string
[tempString appendString:[NSString stringWithCString:(const char*)charstring encoding:[self pageEncoding]]];
//NSLog(@"string: %@", tempString);
//get the space after this string
CGPDFReal r = 0;
if (n+1 < CGPDFArrayGetCount(array)) {
CGPDFArrayGetNumber(array, n+1, &r);
// multiply by the font size
CGFloat k = r;
k = -k/1000 * self.tmatrix.a * self.fontSize;
CGFloat kKern = self.kern * self.tmatrix.a;
k = k + kKern;
// add the location and kern to the array
NSNumber *tempKern = [NSNumber numberWithFloat:k];
NSLog(@"tempKern address: %p", tempKern);
[kernArray addObject:[NSArray arrayWithObjects:[NSNumber numberWithInt:[tempString length] - 1], tempKern, nil]];
}
}
}
// create an attribute string
CFMutableAttributedStringRef attString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 10);
CFAttributedStringReplaceString(attString, CFRangeMake(0, 0), (CFStringRef)tempString);
//apply overall kerning
NSNumber *tkern = [NSNumber numberWithFloat:self.kern * self.tmatrix.a * self.fontSize];
CFAttributedStringSetAttribute(attString, CFRangeMake(0, CFAttributedStringGetLength(attString)), kCTKernAttributeName, (CFNumberRef)tkern);
//apply individual kern attributes
for (NSArray *kernLoc in kernArray) {
NSLog(@"kern location: %i, %i", [[kernLoc objectAtIndex:0] intValue],[[kernLoc objectAtIndex:1] floatValue]);
CFAttributedStringSetAttribute(attString, CFRangeMake([[kernLoc objectAtIndex:0] intValue], 1), kCTKernAttributeName, (CFNumberRef)[kernLoc objectAtIndex:1]);
}
CFAttributedStringReplaceAttributedString([self cfAttString], CFRangeMake(CFAttributedStringGetLength([self cfAttString]), 0), attString);
//release
CFRelease(attString);
[kernArray release];
}
这似乎取决于以下几点:
#0 0x942c7ed7 in objc_msgSend ()
#1 0x00000013 in ?? ()
#2 0x0285b827 in CFAttributedStringSetAttribute ()
#3 0x0000568f in op_TJ (scanner=0x472a590, info=0x4a32320) at /Users/Richard/Desktop/AppTest/PDFHighlight 2/PDFScannerOperators.m:251
有什么想法吗?看起来我正在重写内存或者试图访问已经更改的内存,但我不知道。如果我能提供更多信息,请告诉我
谢谢,
Richard你的崩溃看起来像是某个地方过度释放的结果。很难找到问题所在,特别是当你把核心基础和可可混合在一起的时候。核心基础内存管理规则不同, 我想我会从CFAttributedStringSetAttribute中提取所有对数据的引用,这样我就可以记录它们或使用调试器检查它们,如下所示:
NSNumber* rangeStart = [kernLoc objectAtIndex:0]; // Debug: make sure it is a number
NSNumber attrValue = [kernLoc objectAtIndex:1]; // Debug: make sure it is a number
CFRange range = CFRangeMake([rangeStart intValue], 1); // Debug: make sure it is a valid range for the string
CFAttributedStringSetAttribute(attString, range, kCTKernAttributeName, (CFNumberRef)attrValue)
后续-看起来CFAttributedStringSetAttributes(复数)是一个不错的选择。我仍然需要在我的程序中实现它,但是在一个小测试中,这个函数允许我覆盖以前定义的值,而不会导致EXC_BAD_访问崩溃。如果能在某个地方记录下来,那就太好了。希望这能帮助其他人。谢谢 嗨,杰里米,谢谢你的建议。我尝试了这个方法,发现在进入CFAttributedStringSetAttribute之前,所有的值都是正确的(范围是w/n界限)。我对值进行了实验,发现崩溃取决于attrValue的值,如果attrValue=tkern(另一个已经应用的kern值),程序就会崩溃。我用CFMutableAttributedString创建了一个简单的测试程序,尝试用相同的值覆盖相同的属性,结果崩溃了!我不想对自己的编码技巧妄自尊大,但这似乎是苹果功能中的一个缺陷。可能是这样吗?当你说“相同的值”时,你是指完全相同的CFNumberRef吗?或具有相同值的不同数字参考?看起来旧的attrValue在被新的attrValue替换之前被释放了,如果它们是同一个对象,这可能是一场灾难。因此,它看起来确实像一个bug,但这可能只是意味着我们都错过了一些东西。尝试将对CFAttributedStringSetAttribute的调用与调用前对属性值的调用CFRetain和调用后对属性值的调用CFRelease括起来。嘿,JeremyP,你找到解决方案了吗,当我在pdf中搜索时也发生了同样的情况,但是对这行进行评论会阻止我不想做的事情。如果你对此都做好了准备,那么请帮助我。谢谢你的更新-这也解决了我的问题。
NSNumber* rangeStart = [kernLoc objectAtIndex:0]; // Debug: make sure it is a number
NSNumber attrValue = [kernLoc objectAtIndex:1]; // Debug: make sure it is a number
CFRange range = CFRangeMake([rangeStart intValue], 1); // Debug: make sure it is a valid range for the string
CFAttributedStringSetAttribute(attString, range, kCTKernAttributeName, (CFNumberRef)attrValue)