Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone CFAttributedStringSetAttribute和NSNumber中的EXC\u错误\u访问?_Iphone_Objective C_Exc Bad Access - Fatal编程技术网

Iphone CFAttributedStringSetAttribute和NSNumber中的EXC\u错误\u访问?

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 =

在我正在开发的一个objective c应用程序中,我遇到了一个令人恼火的EXC_BAD_访问错误。如果您能提供任何帮助,我们将不胜感激。我尝试了针对此错误的常规调试方法(打开NSZombieEnabled,检查retain/release/autorelease以确保我没有尝试访问解除分配的对象,等等),但似乎没有任何帮助

基本上,错误总是发生在该函数中:

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];


}
这似乎取决于以下几点:

  • 如果[kernLoc objectAtIndex:1]引用了一个[NSNumber numberWithFloat:k],其中k=0(换句话说,如果k=0高于我填充kernArray的位置),那么程序几乎立即崩溃

  • 如果我注释掉行k=k+kKern,程序崩溃需要更长的时间,但最终会崩溃(为什么崩溃会依赖于这个值?)

  • 如果我将CFRangeMake的长度从1更改为0,程序崩溃的时间会更长,但最终还是会崩溃。(我不认为我试图访问attString的边界之外的内容,但我是否遗漏了什么?)

  • 当它崩溃时,我会得到类似的结果:

    #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)