[petsc-users] question about the PETSc Vec object and C++ destructors

Vijay S. Mahadevan vijay.m at gmail.com
Thu Feb 6 00:53:39 CST 2014


The simplest fix would be to implement the copy constructor/assignment
overload for the object and increase the reference count of vector v.
On object destruction, the VecDestroy will dereference accordingly
until the last object which will actually free the vector allocation.

http://www.mcs.anl.gov/petsc/petsc-dev/docs/manualpages/Sys/PetscObjectReference.html

Vijay

On Thu, Feb 6, 2014 at 12:12 AM, Mohammad Mirzadeh <mirzadeh at gmail.com> wrote:
> There are couple of things you are doing wrong here!
>
>> Shouldn't it be destroying the Vec declared by the very first "thing t",
>> and hence throwing an error saying that you can't destroy a v that has not
>> been created?
>
> No. The destructor of an object is called when either 1) manually call
> `delete` on an instance allocated via `new` or 2) when the object is
> allocated on the stack and goes out of scope. In your case the destructor
> for `t` is called when program reaches the end of `main` i.e. when it
> terminates.
>
> In your case, you are first creating an empty object using the default ctor
> and then assigning it to a temporary object `thing(2)`. Once the assignment
> is done, the destructor of the temporary object is called. Also note that
> since you have not implemented an assignment operator for your class, the
> default is tiled which merely copies `x` which is most certainly what you
> want since in PETSc `Vec` is simply an opaque pointer. This means to
> properly be able to copy one `thing` to another you need to implement the
> assignment operator and most probably also the copy ctor . See
> http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three for
> more details on this.
>
> Also If you are going to depend on dtor to destroy pets objects, you need to
> implement a class that initializes and finalizes PETSc through ctor and dtor
> and call it before calling any other object. Otherwise all other classes
> will be calling their dtors after PetscFinalize. Something like this should
> serve the purpose
>
> class PetscSession{
> public:
> PetscSession(int argc, char* argv[]){
> PetscInitialize(&argc, &argv, NULL, NULL);
> }
> ~PetscSession(){
> PetscFinalize();
> }
> };
>
> int main(int argc, char* argv[]){
> PetscSession petsc(argc, argv);
> // All other classes come after PetscSession has been called
> return 0;
> }
>
>
>
> On Wed, Feb 5, 2014 at 7:14 PM, Matthew Knepley <knepley at gmail.com> wrote:
>>
>> On Wed, Feb 5, 2014 at 8:02 PM, David Liu <daveliu at mit.edu> wrote:
>>>
>>> Hi, this is a question mainly to clear up my understanding of what the
>>> Vec object is. Consider the following C++ code:
>>>
>>> //=========================
>>>
>>> #include <petsc.h>
>>>
>>>
>>>
>>> class thing{
>>>
>>> public:
>>> Vec x;
>>> thing(){};
>>> thing(int N){
>>> PetscPrintf(PETSC_COMM_WORLD, "x before create = %i\n", x);
>>> VecCreateSeq(PETSC_COMM_SELF, N, &x);
>>> PetscPrintf(PETSC_COMM_WORLD, "x after create = %i\n", x);
>>> }
>>> ~thing(){
>>> PetscPrintf(PETSC_COMM_WORLD, "x before destroy = %i\n", x);
>>> VecDestroy(&x);
>>> PetscPrintf(PETSC_COMM_WORLD, "x after destroy = %i\n", x);
>>> }
>>> };
>>>
>>>
>>> int main(int argc, char** argv){
>>>
>>> PetscInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL);
>>>
>>> thing t;
>>> PetscPrintf(PETSC_COMM_WORLD, "x before everything = %i\n", t.x);
>>> t = thing(2);
>>> PetscPrintf(PETSC_COMM_WORLD, "x after everything = %i\n", t.x);
>>> PetscFinalize();
>>> }
>>>
>>> //=========================
>>>
>>> The output, when run sequentially, is
>>>
>>> x before everything = 0
>>> x before create = 0
>>> x after create = -326926224
>>> x before destroy = -326926224
>>> x after destroy = 0
>>> x after everything = -326926224
>>>
>>> (among some unimportant error messages). If I try to VecGetSize(t.x, &N),
>>> immediately after the line "t = thing(2)", I get an error indicating that
>>> t.x has been destroyed.
>>>
>>> This behavior, as well as the printed output, suggests that the
>>> destructor being called during the line "t = thing(2)" is destroying the Vec
>>> just created by "thing(2)". Shouldn't it be destroying the Vec declared by
>>> the very first "thing t", and hence throwing an error saying that you can't
>>> destroy a v that has not been created?
>>
>>
>> This has nothing to do with Vec, it is about C++ copy semantics. This is
>> why I would
>> never tell someone to use C++.
>>
>>    Matt
>>
>> --
>> What most experimenters take for granted before they begin their
>> experiments is infinitely more interesting than any results to which their
>> experiments lead.
>> -- Norbert Wiener
>
>


More information about the petsc-users mailing list