Hey Piotrek,

Memory leaks shouldn't happen if the refcounter implementation does its job
correctly.
Also, the memory block associated to the m_pickedObjects variable is
automatically asked to be
freed when your class is destroyed.
You could also eliminate the "CRefArray::Clear()" call which seems useless
here (you could
maybe gain some useconds) since the object could be destroyed when
assignment is done.

jo



2012/5/2 piotrek marczak <[email protected]>

>   Thank you for detailed reply!
> I didn’t know about refcount concept. It seems much better (faster)
> solution than copying data.
> So, If I understood correctly your example, my function, called multiple
> times, won’t lead to memory leaks.
>  *From:* jo benayoun <[email protected]>
> *Sent:* Wednesday, May 02, 2012 10:50 AM
> *To:* [email protected]
> *Subject:* Re: CRefArray doesn't respect C++ copy semantics
>
>  Hey Piotrek,
>
> We don't know about the CRefArray implementation, so I will just mention
> how things would happen using common programming practices in cpp.
>
> Heavy data structures are usually implemented by separating the actual
> datas from the interface the client is using (methods).
> The datas are encapsulated in really small containers often called POD
> because they are similar to C structures.
> Considering operations like copy by value or assignment are really heavy
> during runtime (creation of a new object and then deep copy of the datas),
> a common practice is to share those POD objects between interfaces
> (often, copies or assigned variables are only temporary during functions
> calls or just for holding a content while manipulating multiple variables).
> An another mechanism (refcounter, smart pointers, ...) is often used in
> complement to keep a track of those objects which can be shared between
> multiple classes to be sure they are deleted correctly.
>
> The idea, is what you are manipulating with your code is not the real
> datas, but just interfaces. COM objects use similar concepts.
> Some libraries make those mechanisms transparent (often the case in cpp)
> and some others (often in c due to the language itself), you have to do it
> by yourself (like with the python c api).
>
>  What would happen in the case of your example is:
>
> when the class is instanciated :
> -> m_pickedObjects = new CRefArray ()
> -> m_pickedObjects->data =  new Data
> -> m_pickedObjects->data->refcount = 1.
>
> at the beginning of your block
>  -> l_moveableObjects = new CRefArray
> -> l_moveableObjects->data = new Data
> -> l_moveableObjects->data->refcount = 1.
>
> you assigned l_moveableObjects to m_pickedObjects
> -> m_pickedObjects->data->refcount - 1
> -> m_pickedObjects->data->refcount == 0 ? delete m_pickedObjects->data :
> do nothing
> -> m_pickedObjects->data = l_moveableObjects->data
> -> l_moveableObjects->data->refcount + 1       (now equal to 2, because
> shared between 2 objects, m_picked and l_moveable)
>
> at the end of your block
>  -> l_moveableObjects->data->refcount - 1
> -> l_moveableObjects ->data->refcount == 0 ? delete l_moveableObjects
> ->data : do nothing        (in this case, the refcount is equal to 1,
> because still shared by m_picked)
>
> Also, the big differences between the copy constructor and the assignement
> operator are:
> -  the copy constructor is a constructor, and when its called, it means a
> new object is being created.
> -  the assignement is just an overloaded operator (=method) returning an
> object (new or not, usually a reference of itself)
> -  during an assignment, if the object passed as rvalue is itself (in the
> case 'm_picked = m_picked'), nothing is done and we just return a reference
> of itself (*this)
> -  during a copy constructor call, if the object passed as parameter is
> itself, a new object is still created.
>
> I hope Marc Andre will correct me if I'm wrong to suppose CRefArray
> implementation is following similar guidelines.
> :)
> jo
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> 2012/5/1 piotrek marczak <[email protected]>
>
>> void UpdateCollisionObjects(**ToolContext &in_ctxt)
>> {
>>       m_pickedObjects .Clear();
>>       CRefArray l_moveableObjects;
>>
>>       // fill  l_moveableObjects with cref()s...
>>
>>        m_pickedObjects = l_moveableObjects;
>> }
>>
>> So why this one is working? If it's just referencing to local class, not
>> making deep copy, and local class is destroyed on function's end?
>>
>> -----Oryginalna wiadomość----- From: Marc-Andre Belzile
>> Sent: Tuesday, May 01, 2012 3:09 PM
>> To: [email protected].**com <[email protected]>
>> Subject: RE: CRefArray doesn't respect C++ copy semantics
>>
>>
>> I say .... CRefArray copy ctor is buggy!
>>
>> thanks for reporting.
>>
>> -mab
>>
>> From: 
>> softimage-bounces@listproc.**autodesk.com<[email protected]>[mailto:
>> softimage-bounces@**listproc.autodesk.com<[email protected]>]
>> On Behalf Of Nicolas Burtnyk
>> Sent: Monday, April 30, 2012 9:05 PM
>> To: [email protected].**com <[email protected]>
>> Subject: Re: CRefArray doesn't respect C++ copy semantics
>>
>> I opened a case with support for this.  We'll see what they say...
>>
>> On Mon, Apr 30, 2012 at 5:59 PM, Alok Gandhi <[email protected]<**
>> mailto:[email protected]**>> wrote:
>> You are right Jo, I mentioned the wrong prototype, what I wanted to quote
>> was the Copy Constructor and the assignment operator. Sorry about the
>> confusion. I clicked on the wrong link. Of course what Nicolas was using
>> was a copy constructor, since both the class methods one after another in
>> the docs, I copy-pasted in haste the wrong one. Anyways, yes Nicolas what
>> you are saying is true regarding the unexpected behavior.
>>
>> The problem is they're treating CRefArray like it's a reference to an
>>> array of CRefs rather than just a straight-up array of CRefs.
>>>
>> That is exactly what is happening here for sure, I concur.
>>
>> Maybe the new dev team could explain this better for the benefit of all
>> the developers as this could seriously cause big time debugging headaches.
>> Thanks for finding this out Nicolas !
>>
>> Error! Filename not specified.
>>
>> On 4/30/2012 8:03 PM, jo benayoun wrote:
>> in this case,
>>
>> """
>> CRefArray a1;
>> a1.Add(CRef());
>> a1.Add(CRef());
>> CRefArray a2(a1);
>> a2.Add(CRef());
>> """
>>
>> The copy constructor is invoked and is not the one you mentioned Alok but
>> this one "CRefArray(const CRefArray &other)" which have different behaviors
>> and purposes than the overloaded assignment operator.
>>
>> """Copy constructor is called every time a copy of an object is made.
>> When you pass an object by value, either into a function or as a function's
>> return value, a temporary copy of that object is made.
>>
>> Assignment operator is called whenever you assign to an object.
>> Assignment operator must check to see if the right-hand side of the
>> assignment operator is the object itself. It executes only the two sides
>> are not equal
>> """
>>
>> Referring to the docs : "Constructs a CRefArray<http://download.**
>> autodesk.com/global/docs/**softimage2012/en_us/sdkguide/**
>> si_cpp/classXSI_1_1CRefArray.**html<http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/si_cpp/classXSI_1_1CRefArray.html>>
>> object from another CRefArray<http://download.**autodesk.com/global/docs/
>> **softimage2012/en_us/sdkguide/**si_cpp/classXSI_1_1CRefArray.**html<http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/si_cpp/classXSI_1_1CRefArray.html>>
>> object." which is the expected behavior.
>>
>> For completeness, the copy constructor in the case of an array, a string,
>> a ptr or whatever container has a main purpose to "pass" an implicit shared
>> memory block to save memory specially in
>> the case of "passing arguments by value". A deep copy is done only at the
>> first call of a method non-const which should create a brand new underlying
>> object (concept called copy-on-write).
>> In this case, it seems its not what happens ... which is a bug in all
>> case unless its a wanted behavior and it should be specified in the doc !
>> A more comprehensible example is the python "list" example:
>> doing an assignment "mylist = myotherlist" creates a shallow copy and
>> returns the "myotherlist" object to the mylist which is not the case of
>> calling the ctor directly with "mylist = list(myotherlist)". That's a
>> behavior that could be implemented here.
>>
>> """
>> mylist = [1, 2]
>> print mylist
>> myotherlist = mylist
>> mylist.append(6)
>> print mylist
>> print myotherlist
>> myoolist = list(mylist)
>> mylist.append(9)
>> print mylist
>> print myotherlist
>> print myoolist
>> """
>>
>>
>> "Set<http://download.autodesk.**com/global/docs/softimage2012/**
>> en_us/sdkguide/si_cpp/**classXSI_1_1CRefArray.html#**
>> acb58b1fecf704752ebcf59a50444c**f37<http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/si_cpp/classXSI_1_1CRefArray.html#acb58b1fecf704752ebcf59a50444cf37>>
>> (const CValueArray<http://download.**autodesk.com/global/docs/**
>> softimage2012/en_us/sdkguide/**si_cpp/classXSI_1_**1CValueArray.html<http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/si_cpp/classXSI_1_1CValueArray.html>>
>> &in_valarray)"
>> I dont see any overloaded cast method nor ctors for a CRefArray to
>> CValueArray. Even if there was, it would mean that your CValueArray have to
>> be built from a CRefArray before being passed by reference. Which is an
>> overhead instead of using the copy ctor.
>> "const" is a keyword that we use to assure to the compiler, we will not
>> try to modify the underlying memory block nor call any procedures that
>> could do this. Of course, the compiler takes this as serious and do
>> optimizations in consequences which is a good thing for us.
>>
>> jo
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> 2012/4/30 piotrek marczak <[email protected]<**mailto:
>> piotrek.marczak@gmail.**com <[email protected]>>>
>> Maybe a2.Set(a1) or a2+=a1 would work?
>>
>> newbie question
>> isn't "const" keyword a hint that we won't change input array?
>> From: Alok Gandhi<mailto:alok.gandhi@**modusfx.com<[email protected]>
>> >
>> Sent: Tuesday, May 01, 2012 1:31 AM
>> To: [email protected].**com <[email protected]>
>> <mailto:softimage@listproc.**autodesk.com<[email protected]>
>> >
>> Subject: Re: CRefArray doesn't respect C++ copy semantics
>>
>> The docs say that:
>> CRefArray<http://download.**autodesk.com/global/docs/**
>> softimage2012/en_us/sdkguide/**si_cpp/classXSI_1_1CRefArray.**html<http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/si_cpp/classXSI_1_1CRefArray.html>>&
>> operator=
>>
>> (
>>
>> const CRefArray<http://download.**autodesk.com/global/docs/**
>> softimage2012/en_us/sdkguide/**si_cpp/classXSI_1_1CRefArray.**html<http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/si_cpp/classXSI_1_1CRefArray.html>>
>> &
>>
>> in_refArray
>>
>> )
>>
>>
>> Assigns a CRefArray<http://download.**autodesk.com/global/docs/**
>> softimage2012/en_us/sdkguide/**si_cpp/classXSI_1_1CRefArray.**html<http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/si_cpp/classXSI_1_1CRefArray.html>>
>> object to this one.
>> Parameters:
>> in_refArray
>>
>> A constant CRefArray<http://download.**autodesk.com/global/docs/**
>> softimage2012/en_us/sdkguide/**si_cpp/classXSI_1_1CRefArray.**html<http://download.autodesk.com/global/docs/softimage2012/en_us/sdkguide/si_cpp/classXSI_1_1CRefArray.html>>
>> object.
>>
>> Returns:
>> A new reference object.
>>
>> So what I think is happening is that the copy constructor is doing
>> exactly what it is supposed to do and returns the new CRefArray object
>> which still points to a1, 'assigns' is the operative word here. To keep
>> them separate I would rather do:
>>
>>   CRefArray a1;
>>   a1.Add(CRef());
>>   a1.Add(CRef());
>>   CRefArray a2;
>>
>>   for(int i=0; i<a1.GetCount(); i++)
>>   {
>>       a2.Add(a1[i]);
>>   }
>>
>>   a2.Add(CRef());
>>
>>   //a2.Add(CRef());
>>   LONG n1 = a1.GetCount();  // expected n1 == 2
>>   LONG n2 = a2.GetCount();  // expected n2 == 3
>>
>> which gives me correctly:
>>
>> # VERBOSE : cRefArrayTest_Execute called
>> # VERBOSE : Count a1: 2
>> # VERBOSE : Count a2: 3
>>
>>
>> Error! Filename not specified.
>>
>> On 4/30/2012 7:13 PM, Nicolas Burtnyk wrote:
>> Yeah, exactly as I unfortunately discovered :(
>> On Mon, Apr 30, 2012 at 3:49 PM, Alok Gandhi <[email protected]<**
>> mailto:[email protected]**>> wrote:
>> A quick test gives me following result:
>>
>> # VERBOSE : cRefArrayTest_Execute called
>> # VERBOSE : Count a1: 3
>> # VERBOSE : Count a2: 3
>>
>> Error! Filename not specified.
>>
>> On 4/30/2012 6:24 PM, Nicolas Burtnyk wrote:
>> I ran into this today while trying to figure out why my code was broken.
>> Thought I'd pass this along and hopefully save someone some wasted time
>> in the future...
>>
>> CRefArray a1;
>> a1.Add(CRef());
>> a1.Add(CRef());
>> CRefArray a2(a1);
>> a2.Add(CRef());
>> LONG n1 = a1.GetCount();  // expected n1 == 2
>> LONG n2 = a2.GetCount();  // expected n2 == 3
>>
>> I expected a2 to be a copy of a1 before the last add and so I assumed a1
>> would have 2 elements.
>> Instead, I was surprised to find that n1 == n2 == 3!
>>
>>
>>
>> No virus found in this message.
>> Checked by AVG - www.avg.com<http://www.avg.com**>
>> Version: 2012.0.1831 / Virus Database: 2090/4557 - Release Date: 10/17/11
>> Internal Virus Database is out of date.
>>
>>
>>
>> No virus found in this message.
>> Checked by AVG - www.avg.com<http://www.avg.com**>
>> Version: 2012.0.1831 / Virus Database: 2090/4557 - Release Date: 10/17/11
>> Internal Virus Database is out of date.
>>
>>
>>
>> No virus found in this message.
>> Checked by AVG - www.avg.com<http://www.avg.com**>
>> Version: 2012.0.1831 / Virus Database: 2090/4557 - Release Date: 10/17/11
>> Internal Virus Database is out of date.
>>
>>
>

Reply via email to