Official Forum for Programming in Objective-C (the iPhone Programming Language) - Stephen Kochan
December 16, 2017, 09:04:18 PM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
 
   Home   Help Search Login Register Chat  
Pages: 1 [2] 3 4 ... 7   Go Down
  Print  
Author Topic: Program 7.5 - 7.6 stuck  (Read 34340 times)
Razz2
Newbie
*
Posts: 11


« Reply #15 on: March 25, 2009, 04:45:41 PM »

OK, I have read everything here and in the book and just want to clarify something... I am going to try this step by step mostly...

sum is a Fraction (Fraction 1 lets say) declared, allocated and initialized in 'main'.

sum2 is declared in main but not initialized or allocated.

<START THE FOR LOOP HERE>

Upon executing the method 'add' for the sum fraction (Fraction 1) the result is a new fraction stored in sum2.

Code: (Objective-C)
sum2 = [sum add: aFraction]
;

sum2 is now an allocated and initialized fraction (Fraction 2 lets say)

Cool, we have two fractions and therefore two memory areas that at some point could need to be released. (right?)

sum (Fraction 1) is then released leaving us with only the memory used by sum2 (Fraction 2).

Code: (Objective-C)
[sum release];

(NOTE: I think that without this next line we would have had to release sum2 at some point.?.?)

sum is set to equal sum2

Code: (Objective-C)
sum = sum2;

So now we again have 2 Fractions BUT have only one Fraction memory area to worry about releasing later, and it can be referred to by either sum or sum2. (Fraction 1 and Fraction 2 are the same value and memory?)

<END THE FOR LOOP HERE>

Once the loop ends technically both sum and sum2 still exist. But, they are equal to each other... meaning they are the same piece of memory with all it's related values and variables.

So, the final release, as you hint in another thread, could be:

Code: (Objective-C)
[sum release];

or

Code: (Objective-C)
[sum2 release];

Does that make sense and if not am I in the correct state of mind?

Logged
esc
Global Moderator
Full Member
*****
Posts: 230


« Reply #16 on: March 25, 2009, 05:17:05 PM »

Hi Razz2,

What you outlined makes sense.

Technically, the program deals with 3 fractions (the 3 Fraction class objects are aFraction, sum, and sum2).

If these 3 were not objects, let's say they are type int, then
sum2 = [sum add: aFraction] is like "sum = sum + aFraction".

However, because (these are objects) the add: method returns a fraction and the memory for that fraction is allocated from within the add: method, we need a way to release the return value of add:.

After the first loop, the program releases the (previous) memory that add: allocated.
Code: (Objective-C)
sum2 = [sum add: aFraction];
[sum release];

After the for loop is over, you are correct, sum and sum2 point to the same object in memory and a release message to either (but only one) would release the (last) memory allocated by add:.

I hope this helps and not confuse any :-)
Logged
mdeh
Full Member
***
Posts: 166


« Reply #17 on: March 25, 2009, 10:52:20 PM »

OK, I have read everything here and in the book and just want to clarify something... I am going to try this step by step mostly...

sum is a Fraction (Fraction 1 lets say) declared, allocated and initialized in 'main'.


sum is a variable which  points to an instance of the Fraction class. Just think of sum as an instance of Fraction, which has memory allocated.


Quote
sum2 is declared in main but not initialized or allocated.


sum2 is a variable of type Fraction...nothing more.

Quote
<START THE FOR LOOP HERE>

Upon executing the method 'add' for the sum fraction (Fraction 1) the result is a new fraction stored in sum2.

sum2 now points to an instance of Fraction which **it did not allocate**, but which was passed to it, and which is **distinct** from sum.


Quote
sum2 is now an allocated and initialized fraction (Fraction 2 lets say)

I think this may be somewhat overthinking it and causing confusion. sum2, as I said above is pointing at an instance that was **created** elsewhere and you were simply handed a ref to it.  The key here is that the creation of this particular instance violates one of the rules ( as Steve explains somewhere)...and perhaps understanding that rule might throw some light into this issue. The rule says if you allocate , then you release ( you being the method). So, in this case, sum2 is **handed** a ref to an area of memory that suddenly has become it's  responsibility to manage.


Quote
sum (Fraction 1) is then released leaving us with only the memory used by sum2 (Fraction 2).

Do you see **why** you are releasing this? You **could** simply assign sum2 to sum, or even more simply just assign the return from the add: method **directly** to sum. However, in this case, the memory sum **used** to point to ( the *old* instance) just sits in memory without anything pointing to it, and by the rules that you have agreed to( that you will be responsible for releasing what you allocate), will just be left alone. Moreover, once you have *re-pointed* the pointer, there is no way to release this either. That's why all this is done. You **release** sum, then point  it to the instance  sum2 is pointing at. There is now just **one** instance of Fraction ( one area of memory). You can reassign sum2 to your hearts content, and it will not create more memory.



Code: (Objective-C)
[sum release];


Quote
(NOTE: I think that without this next line we would have had to release sum2 at some point.?.?)

NO!! The two are **not** related. You are releasing sum, so that you can point to the **new** instance that was created in the other method and to which  sum2 currently points, and not leak memory. Remember you are doing this because you want sum to hold a running total.  If you were to release sum2, you would be setting the instance ( that contains the running total) to nil,  and the program will crash because sum will now **also** be nil and any message to it will be meaningless.
(in fact, I found the old program and released sum2, and got "EXC_BAD_ACCESS", which is the program trying to access memory that it is not allowed to)

Quote
sum is set to equal sum2

Code: (Objective-C)
sum = sum2;

So now we again have 2 Fractions

Nope!!!  you have **one** instance of Fraction...remember, you released sum. What you **do** have are 2 variables pointing to the **one** instance of Fraction

Quote
BUT have only one Fraction memory area to worry about

Yes...but not for the reason you gave.

Quote
Once the loop ends technically both sum and sum2 still exist. But, they are equal to each other... meaning they are the same piece of memory with all it's related values and variables.

Not sure what you mean by all related values and variables...at the end of the loop, sum and sum2 are equal, by which I mean they both ref the same instance of Fraction.


Quote
So, the final release, as you hint in another thread, could be:

Code: (Objective-C)
[sum release];

or

Code: (Objective-C)
[sum2 release];

Yes...but **not** both.

OK...take a deep breath. Here is the big picture.

In one method ( which happens to be a loop) ...you are  starting with an instance of fraction referenced by a variable. In **another** method, you create a second instance of Fraction referenced by another variable. Your task is to store this instance in the **first** variable. So, how do you do this and not leak memory. Answer. Sum2!  Does that make sense now?  Or **I ** could be completely wrong Grin
« Last Edit: March 26, 2009, 01:41:17 AM by mdeh » Logged
mdeh
Full Member
***
Posts: 166


« Reply #18 on: March 25, 2009, 11:09:03 PM »


Technically, the program deals with 3 fractions (the 3 Fraction class objects are aFraction, sum, and sum2).

Hi Wendy...Firstly **Congratulations** on becoming the first prodigy of the Kochan book!!!   Grin Clearly a testament to the clarity of Steve's style!!!! 

I am wondering about the *3* objects above. The way I read it there are 2 objects. aFraction, and sum. Sum2 at various times points to an object, but never really asks for any memory itself. So the whole exercise here is to take sum ( an object) , release it, point it to the next object which was generated in another method.....ad infinitum.?? Or am I missing something too. ( I am here at work, so do not have the book with me). 
« Last Edit: March 26, 2009, 01:43:56 AM by mdeh » Logged
Mike
Jr. Member
**
Posts: 51


Email
« Reply #19 on: March 26, 2009, 11:40:46 AM »

Hi Steven,


I think I see. Simplified

repeat lines 1 - 3
1. sum2 = sum + fraction <--- sum2 = current fraction + new fracton
2. sum = nil  <--- because it contain the previous fraction
3. sum = sum2  <--- now it contains the current fraction

Mike

Logged
mdeh
Full Member
***
Posts: 166


« Reply #20 on: March 26, 2009, 11:52:12 AM »

Hi Steven,


I think I see. Simplified

repeat lines 1 - 3
1. sum2 = sum + fraction <--- sum2 = current fraction + new fracton
2. sum = nil  <--- because it contain the previous fraction

Well, I agree with your action. But the **reason** you are doing this is **not** because it **points to** a fraction/memory, the reason you set it to nil is because you wish to reassign it to a new instance/fraction/memory and you responsibly release it, so it does not leak.

Quote
3. sum = sum2  <--- now it contains the current fraction

sum and sum2 now point to the **same** instance/fraction/memory.
Logged
esc
Global Moderator
Full Member
*****
Posts: 230


« Reply #21 on: April 02, 2009, 01:07:50 PM »

I am wondering about the *3* objects above. The way I read it there are 2 objects. aFraction, and sum. Sum2 at various times points to an object, but never really asks for any memory itself. So the whole exercise here is to take sum ( an object) , release it, point it to the next object which was generated in another method.....ad infinitum.?? Or am I missing something too. ( I am here at work, so do not have the book with me). 

Hi Michael,

I missed your reply until now...sorry for not replying sooner.  You are right -- program 7.6 has 2 (Fraction class) objects (aFraction and sum).  sum2 is only a pointer to the object referenced by sum.
Logged
wellaged37
Newbie
*
Posts: 39


« Reply #22 on: April 03, 2009, 06:33:59 AM »

Some questions about the add: method:
1. Is result a local variable?
2. Is it destroyed as the method returns?
3. If it is destroyed, how can it be returned to the main program?

A separate question:
Let's say that an object is released and deallocated. Is the address to the object held by the pointer zeroed? Or is the memory location of the object zeroed? In other words how is the memory freed-up so that it can be re-used? I noticed that when I am debugging I am not aware of any changes in the Debugger pane's variables when deallocation takes place.

Thanks, John

Logged
skochan
Administrator
Hero Member
*****
Posts: 3114



« Reply #23 on: April 03, 2009, 06:46:25 AM »

John,

Read this thread and see if it answers most, if not all, of your questions:

http://classroomm.com/objective-c/index.php?topic=427.0

Cheers,

Steve
Logged
hdelman
Newbie
*
Posts: 21


« Reply #24 on: April 05, 2009, 11:27:42 PM »

I've read this entire thread, as well as the other threads that it references.  I do believe I finally understand it, but one thing is still bothering me. 

Is the code written the way it is for any reason other than to help teach us about memory management?  Otherwise, why not just go back and simplify the add method so that it looks like it did on the top of page 150?  It doesn't allocate the new object - result - and the object sum actually accumulates the sum, which is what we want.  No extra alloc and release, and fewer lines of code.

Howard
Logged
skochan
Administrator
Hero Member
*****
Posts: 3114



« Reply #25 on: April 06, 2009, 01:11:50 AM »

Howard,

That's  a good question!  We modified the add: method because the original version overwrites its receiver with the result of the operation.  The more generalized version returns the result without modifying the receiver or the argument.  Of course, as the designer of the Fraction class (or any class you implement) you can make a pragmatic decision on how a method like that should operate based upon the use of the class in programming applications. 

You could even implement two methods:  add: and addInto:; the first could allocate and return a new Fraction object that represents the sum of the two Fractions, the second could add the Fraction into the receiver, as was done with the first version of the add: method.

Cheers,


Steve Kochan
« Last Edit: April 06, 2009, 11:00:04 AM by skochan » Logged
hdelman
Newbie
*
Posts: 21


« Reply #26 on: April 06, 2009, 07:11:50 PM »

Thanks, Steve, for the response.  I understand your points, and I certainly see the advantage of an add: method that doesn't clobber the original values.  But I keep thinking about this, though, and another thought came to mind.  Might it be less confusing if the result object was created by the main routine, and then passed to the add: method?  For example:

-(void) add: (Fraction *) f save: (Fraction *) result
{   
   int resultNum, resultDenom;
   
   resultNum = (numerator * f.denominator) + (denominator * f.numerator);
   resultDenom = denominator * f.denominator;
   [result setTo: resultNum over: resultDenom];
   [result reduce];
}

Then, in main, I would alloc and init sum2 along with aFraction and sum.  The "for" loop becomes:

   for (i=1; i <= n; ++i){
      [aFraction setTo: 1 over: pow2];
      [sum add: aFraction save: sum2];
      sum = sum2;
      pow2 *= 2;
   }
     
All three instances of Fraction are released at the end.

Seems much clearer, and with no worry about memory leakage.

Howard
Logged
skochan
Administrator
Hero Member
*****
Posts: 3114



« Reply #27 on: April 06, 2009, 07:33:49 PM »

However, take a closer look at your code:

Code: (Objective-C)
   for (i=1; i <= n; ++i){
      [aFraction setTo: 1 over: pow2];
      [sum add: aFraction save: sum2];
      sum = sum2;      <=======
      pow2 *= 2;
   }

The indicated line is just copying a pointer, and not the the Fraction's instance variables (that is, not its numerator and denominator).  At the end of the assignment, sum and sum2 will point to the same fraction, and the handle to the original sum fraction will be lost, meaning it can't be released later.  Because sum and sum2 will point to the same fraction, the next time through the loop  sum (which is really now sum2 from the last time through the loop) will be added with aFraction and the result stored back into sum2, effectively doing what the first version of the add: method did.

Cheers,

Steve Kochan

Logged
hdelman
Newbie
*
Posts: 21


« Reply #28 on: April 06, 2009, 08:29:55 PM »

Got it.  Thanks for being a patient teacher.  I understand it, but it is not intuitive.

H.
Logged
ariel_mirahy
Newbie
*
Posts: 11


Email
« Reply #29 on: April 11, 2009, 03:10:47 PM »

My program 7.6 is not working, any ideas why?

Main Program.m
Code: (Objective-C)
#import "Fraction.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

Fraccion *frac1 = [[Fraccion alloc] init];
Fraccion *fracSuma = [[Fraccion alloc] init], *fracSuma2;

int nFraccion, expALa2 = 2;

frac1.numerador = 0;

NSLog(@"\n\nHasta Que Fraccion Sumatoria Deseas Calcular?:\n\n");
scanf ("%i", &nFraccion);

for (int i = 1; i <= nFraccion; ++i)
{
frac1.denominador = expALa2;
fracSuma2 = [fracSuma sumar: frac1];
fracSuma.release;
fracSuma = fracSuma2;
expALa2 *= 2;
}

    NSLog(@"\n\nSe Calcularon %i Fracciones Sumadas, El Resultado Es %g!\n\n", nFraccion, fracSuma.convertirAEntero);

frac1.release;
fracSuma.release;

    [pool drain];
    return 0;
}

Also, instead of releasing the sum in the for loop can we release it directly from the method?, Something like:
Code: (Objective-C)
-(Fraccion *) sumar: (Fraccion *) f 
{
Fraccion *frac3 = [[Fraccion alloc] init];

int resDenominador, resNumerador;

resNumerador = (numerador * f.denominador) + (denominador * f.numerador);
resDenominador = denominador * f.denominador;

frac3.numerador = resNumerador;
frac3.denominador = resDenominador;
frac3.reducir;

return frac3;

       ]frac3.release;// WE RELEASE IT AFTER IT HAS RETURNED THE VALUE TO US
}


Can We?
« Last Edit: April 11, 2009, 11:24:18 PM by ariel_mirahy » Logged
Pages: 1 [2] 3 4 ... 7   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Entire forum contents ゥ 2009 classroomM.com. All rights reserved.