EXC_BAD_ACCESS в CFAttributedStringSetAttribute и NSNumber? - PullRequest
3 голосов
/ 06 июня 2010

Я получаю бешеную ошибку EXC_BAD_ACCESS в целевом приложении c, над которым я работаю. Любая помощь, которую вы можете предложить, будет высоко ценится. Я попробовал обычные методы отладки для этой ошибки (включение 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];


}

Программа всегда вылетает из-за строки

CFAttributedStringSetAttribute(attString, CFRangeMake([[kernLoc objectAtIndex:0] intValue], 1), kCTKernAttributeName, (CFNumberRef)[kernLoc objectAtIndex:1])

И, похоже, это зависит от нескольких вещей:

  1. если [kernLoc objectAtIndex: 1] ссылается на [NSNumber numberWithFloat: k], где k = 0 (другими словами, если k = 0 выше, где я заполняю kernArray), то программа почти сразу завершается сбоем

  2. Если я закомментирую строку k = k + kKern, произойдет сбой программы дольше, но в конечном итоге (почему сбой будет зависеть от этого значения?)

  3. Если я изменю длину 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

Есть идеи? Кажется, где-то по пути я перезаписываю память или пытаюсь получить доступ к памяти, которая была изменена, но я понятия не имею. Если есть больше информации, которую я могу предоставить, пожалуйста, дайте мне знать.

Спасибо, Ричард

Ответы [ 2 ]

4 голосов
/ 07 июня 2010

Ваш сбой выглядит как результат переиздания где-то. Трудно отследить, в чем может быть проблема, особенно когда вы смешиваете основную основу с Cocoa. Правила управления памятью различаются для базовой основы.

Я думаю, что я бы извлек все ссылки на данные из CFAttributedStringSetAttribute, чтобы я мог NSLog их или проверить их с помощью отладчика, например:

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)
2 голосов
/ 08 июня 2010

Follow - похоже, что CFAttributedStringSetAttributes (множественное число) - это путь. Мне все еще нужно внедрить его в мою программу, но в небольшом тесте эта функция позволяет мне перезаписывать ранее определенные значения без получения сбоя EXC_BAD_ACCESS. Было бы неплохо, если бы это было где-то задокументировано. Надеюсь, что это помогает другим людям там. Спасибо!

...