Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8922471
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T06:50:39+00:00 2026-06-15T06:50:39+00:00

I’m using ARC and a while loop to adjust several CGPathRefs until they fit

  • 0

I’m using ARC and a while loop to adjust several CGPathRefs until they fit within some constraints I have, and I need access to the paths once the conditions of the while loop are satisfied.

Can someone explain how my code is leaking?

The documentation for the CGCreateCopy… functions say they create a new copy, which you are responsible for releasing. So I believe my code path (the end of the while loop) does release the path references which Instruments is catching and attributing leaked objects to.

The Instrument call outs are denoted in the code below with comments right below the place Instruments was highlighting.

This routine is given a GCSize size that is the size of a rectangle and an int value which is a numerical value that eventually will be shown within the shape created here (dimensions of the shape are somewhat dependent upon the size of the string representation of this value)

I should note that the code does produce the required paths exactly as I want — I’m not asking anyone to debug this block! But it leaks and I don’t understand why.

float lineThickness = size.width;
float perimeterStrokeWidth = lineThickness * 2;
CGSize shadowOffset = CGSizeMake( perimeterStrokeWidth / 1.5, perimeterStrokeWidth * 1.25 );
float shadowBlur = perimeterStrokeWidth * 2.0;

NSString *edgeSymbol = @"°";
CGPathRef rightEdgePath = NULL;
CGPathRef leftEdgePath = NULL;
CGPathRef valueStringPath = NULL;
CGAffineTransform adjust, flip;
float pointsize, deltaX, deltaY, inset, pointSizeThatFits;
CGRect valueRect, edgeRect, leftEdgeRect, rectForValue;

CGSize trialSize = size;
pointsize = size.height;
CGPoint tdc; // top dead center
CGPoint bdc; // bottom dead center

NSLog(@"\n\n");
BOOL done = false;
int attempts = 0;
int attemptsRemaining = 11; // ensure no infinite looping

while ( ! done ) {
    done = YES; // presumptive close!  tests below will reset if they fail
    --attemptsRemaining;

    trialSize = CGSizeMake(trialSize.width, trialSize.height - attempts);
    ++attempts;

    lineThickness = trialSize.height / 60;
    perimeterStrokeWidth = lineThickness * 2;
    shadowOffset = CGSizeMake( perimeterStrokeWidth / 1.5, perimeterStrokeWidth * 1.0 );
    shadowBlur = perimeterStrokeWidth * 2.0;

    pointsize = [UIFont sizeFont:[UIFont fontWithName:@"Alameda"
                                                 size:pointsize]
                       toFitText:edgeSymbol
                      withinRect:CGRectMake(0,
                                            0,
                                            trialSize.width,
                                            trialSize.height)];
    // sizeFont:toFitText:withinRect: is a custom addition to UIFont that
    // recursively tries smaller and smaller pointsize values until the
    // text fits within the rectangle provided.

    CGPathRef tmpRightEdgePath = [edgeSymbol newPathWithFont:[UIFont fontWithName:@"Alameda" size:trialSize.height * 1.1]];
    // newPathWithFont: is a custom addition to NSString that returns a 
    // CGPathRef representing the glyphs that make up the string, rendered in
    // the font (and size) specified

    flip = CGAffineTransformMakeScale(-1.0, 1.0);

    CGPathRef tmpLeftEdgePath = CGPathCreateCopyByTransformingPath(tmpRightEdgePath, &flip);

    edgeRect = CGPathGetBoundingBox(tmpRightEdgePath);

    // Center the symbol vertically in the size we were given (maybe up a little because of the shadow below?)

    deltaY = ( (size.height / 2) - (edgeRect.size.height / 2) - edgeRect.origin.y);

    // Slide it over to the right edge, inset slightly for the shadow
    inset = shadowOffset.width + shadowBlur;
    deltaX = ( trialSize.width - edgeRect.origin.x - edgeRect.size.width - inset);

    adjust = CGAffineTransformMakeTranslation(deltaX, deltaY);
    CGPathRef tmpRightEdgePath1 = CGPathCreateCopyByTransformingPath(tmpRightEdgePath, &adjust);
    CGPathRelease(tmpRightEdgePath);
    tmpRightEdgePath = NULL;
    edgeRect = CGPathGetBoundingBox(tmpRightEdgePath1);

    leftEdgeRect = CGPathGetBoundingBox(tmpLeftEdgePath);
    deltaX = inset - leftEdgeRect.origin.x;
    adjust = CGAffineTransformMakeTranslation(deltaX, deltaY);
    CGPathRef tmpLeftEdgePath1 = CGPathCreateCopyByTransformingPath(tmpLeftEdgePath, &adjust);
    CGPathRelease(tmpLeftEdgePath);
    tmpLeftEdgePath = NULL;

    leftEdgeRect = CGPathGetBoundingBox(tmpLeftEdgePath1);

    rectForValue = CGRectMake(leftEdgeRect.origin.x + leftEdgeRect.size.width,
                                     leftEdgeRect.origin.y,
                                     edgeRect.origin.x - leftEdgeRect.origin.x - leftEdgeRect.size.width,
                                     leftEdgeRect.size.height);

    NSString *valueString = [NSString stringWithFormat:@"%i", value];
    pointSizeThatFits = [UIFont sizeFont:[UIFont fontWithName:@"Futura" size:trialSize.height]
                               toFitText:valueString
                              withinRect:rectForValue];
    valueStringPath = [valueString newPathWithFont:[UIFont fontWithName:@"Futura" size:pointSizeThatFits]];

    valueRect = CGPathGetBoundingBox(valueStringPath);
    deltaY = ( (size.height / 2) - (valueRect.size.height / 2) - valueRect.origin.y);
    deltaX = ( (trialSize.width / 2)  - (valueRect.size.width / 2)  - valueRect.origin.x);
    adjust = CGAffineTransformMakeTranslation(deltaX, deltaY);
    CGPathRef tmpValueStringPath1 = CGPathCreateCopyByTransformingPath(valueStringPath, &adjust);
    CGPathRelease(valueStringPath);
    valueStringPath = NULL;

    valueRect = CGPathGetBoundingBox(tmpValueStringPath1);

    CGPathRef tmpRightEdgePath2;
    CGPathRef tmpLeftEdgePath2;

    if ((valueRect.origin.x + valueRect.size.width) < edgeRect.origin.x) {
        float gapToClose = edgeRect.origin.x - (valueRect.origin.x + valueRect.size.width);
        adjust = CGAffineTransformMakeTranslation(- gapToClose, 0);
        {
            tmpRightEdgePath2 = CGPathCreateCopyByTransformingPath(tmpRightEdgePath1, &adjust);
            // ^^^^ Instruments reports 5.9% of leaks here
            CGPathRelease(tmpRightEdgePath1);
            tmpRightEdgePath1 = NULL;
        }

        adjust = CGAffineTransformMakeTranslation(gapToClose, 0);
        {
            tmpLeftEdgePath2 = CGPathCreateCopyByTransformingPath(tmpLeftEdgePath1, &adjust);
            // ^^^^ Instruments reports 23.5% of leaks here
            CGPathRelease(tmpLeftEdgePath1);
            tmpLeftEdgePath1 = NULL;
        }

        leftEdgeRect = CGPathGetBoundingBox(tmpLeftEdgePath2);
    } else {
        {
            tmpRightEdgePath2 = CGPathCreateCopy(tmpRightEdgePath1);
            CGPathRelease(tmpRightEdgePath1);
            tmpRightEdgePath1 = NULL;
        }
        {
            tmpLeftEdgePath2  = CGPathCreateCopy(tmpLeftEdgePath1);
            CGPathRelease(tmpLeftEdgePath1);
            tmpLeftEdgePath1 = NULL;
        }
        leftEdgeRect = CGPathGetBoundingBox(tmpLeftEdgePath2);
    }

    tdc.x = CGRectGetMidX(rectForValue);
    bdc.x = tdc.x;

    tdc.y = leftEdgeRect.origin.y - (tdc.x - leftEdgeRect.origin.x) * 0.08; // SWAG on the 10% of width

    if ((tdc.y - lineThickness/2.0) < 0) {
        done = NO;
    }

    bdc.y = leftEdgeRect.origin.y + leftEdgeRect.size.height + (leftEdgeRect.origin.y - tdc.y);

    float shadowness = shadowOffset.height;
    if ((bdc.y + shadowness) > size.height) {
        done = NO;
    }

    if (attemptsRemaining <= 0) {
        done = YES;
    }

    // And finally, assign them out if DONE!

    if (done) {
        leftEdgePath = CGPathCreateCopy(tmpLeftEdgePath2);
        // ^^^^ Instruments reports 35.3% of leaks here
        rightEdgePath = CGPathCreateCopy(tmpRightEdgePath2);
        // ^^^^ Instruments reports 35.3% of leaks here
        valueStringPath = CGPathCreateCopy(tmpValueStringPath1);
    }
    CGPathRelease(tmpLeftEdgePath2);
    tmpLeftEdgePath2 = NULL;
    CGPathRelease(tmpRightEdgePath2);
    tmpRightEdgePath2 = NULL;
    CGPathRelease(tmpValueStringPath1);
    tmpValueStringPath1 = NULL;
}
// what follows is the application of those paths within CGContext drawing calls.

I understand from the other helpful answers hereabouts on Instruments and Leaks that the flagged lines are generally where the soon-to-be-leaked object was created. With that in mind I follow downward to see where I might be assigning a new path without first releasing the prior path, but there aren’t any (that I can see — but I’ll admit I’m getting a little bleary eyed looking at this).

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T06:50:40+00:00Added an answer on June 15, 2026 at 6:50 am

    For the benefit of others who find themselves vexed by memory leak problems I’m going to provide the answer to my problem here because the sleuthing process may help you.

    In the middle of the code listing you can see where I inform the compiler that I will soon be using two CGPathRefs, initially inside the scope of an if/then/else, so I needed them allocated (?) outside that block so they are local to my routine.

    CGPathRef tmpRightEdgePath2;
    CGPathRef tmpLeftEdgePath2;
    

    By changing those to:

    CGPathRef tmpRightEdgePath2 = NULL;
    CGPathRef tmpLeftEdgePath2 = NULL;
    

    That cleared up the two leaks being reported as occurring during the if/then/else statement.

    So now my only two remaining leaks are reported inside the if (done) {} block.

    In Instruments, looking at the Leaks tool, the Cycles & Roots -> Leak Cycles -> foo History I see where the 10 memory events end with a RefCt being 1, so clearly a leak:

    #  Category           Event Type    RefCt  ResponsibleLibrary  Responsible Caller
    0  NSMutableRLEArray  Malloc        1      Foundation          -[NSConcreteAttributedString initWithString:attributes:]
    1  NSMutableRLEArray  Release       0      Foundation          -[NSConcreteAttributedString dealloc]
    2  NSMutableRLEArray  Free          0      Foundation          -[NSRLEArray dealloc]
    3  CGPath             Malloc        1      CoreGraphics        CGTypeCreateInstance
    4  CGPath             CFRelease     0      my app              my routine
    5  CGPath             Free          0      my app              my routine
    6  CGPath             Malloc        1      CoreGraphics        CGTypeCreateInstance
    7  CGPath             CFRelease     0      my app              my routine
    8  CGPath             Free          0      my app              my routine
    9  CGPath             Malloc        1      CoreGraphics        CGTypeCreateInstance
    

    So at some point after I thought I was done manipulating my paths there had to be another CGCreateCopy… style call occurring, since a Malloc was called after I had released everything. So by using search/find I worked my way forward through the drawing code and found a last CGPathCreateCopyByTransforming:

    CGAffineTransform slightUp = CGAffineTransformMakeTranslation(0, - lineThickness * 2 );
    leftEdgePath = CGPathCreateMutableCopyByTransformingPath(leftEdgePath, &slightUp);
    rightEdgePath = CGPathCreateMutableCopyByTransformingPath(rightEdgePath, &slightUp);
    

    Which are guaranteed leaks since the retain count went up by one during that copy. So I reworked those to be:

    CGAffineTransform slightUp = CGAffineTransformMakeTranslation(0, - lineThickness * 2 );
    CGMutablePathRef finalLeftEdgePath = CGPathCreateMutableCopyByTransformingPath(leftEdgePath, &slightUp);
    CGPathRelease(leftEdgePath);
    CGMutablePathRef finalRightEdgePath = CGPathCreateMutableCopyByTransformingPath(rightEdgePath, &slightUp);
    CGPathRelease(rightEdgePath);
    

    And then I changed my CGContextAddPath() to match the new “final” paths, and also the final release calls to release the “final” versions and I am leak free!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I have just tried to save a simple *.rtf file with some websites and
I have thousands of HTML files to process using Groovy/Java and I need to
I am using Paperclip to handle profile photo uploads in my app. They upload
I am trying to loop through a bunch of documents I have to put
I have a .ini file as follows: [playlist] numberofentries=2 File1=http://87.230.82.17:80 Title1=(#1 - 365/1400) Example
I'm new to using the Perl treebuilder module for HTML parsing and can't figure
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I am reading a book about Javascript and jQuery and using one of the
link Im having trouble converting the html entites into html characters, (&# 8217;) i

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.