Is it safe to create object pointer on the stack indirectly?

5

My class has a method that returns a pointer to itself, and at some point I use the following:

void classequalquer::metodo() {
    ClasseA * ponteiro = ClasseA().getThis();
    //usa o ponteiro nesse método sem usar delete
}

//Para referências
ClasseA* ClasseA::getThis() {
    return this;
}
    
asked by anonymous 07.03.2017 / 02:31

3 answers

5

The posted post is not secure:

void classequalquer::metodo() {
  ClasseA * ponteiro = ClasseA().getThis();
  //deferenciar o ponteiro aqui é comportamento indefinido
  //o objeto não existe mais
}

ponteiro takes the address of an object created as temporary for the assignment operation. The object is not available at the end of the sequential point that terminates the operation, and ponteiro reference address invalidated. It is illegal to get the address of a rvalue .

Returning the pointer through a method is safe:

Despite the posted snippet, returning the pointer through a method is safe, and the snippet should be adapted to the following form:

void classequalquer::metodo() {
  ClasseA A;
  ClasseA * ponteiro = A.getThis();
  //usa o ponteiro nesse método sem usar delete
  //o objeto ainda existe
}

But the method is unnecessary (and I personally discourage it), any code scope that has access to ClasseA::getThis() also has access to the & operator, which has the function of returning address:

void classequalquer::metodo() {
  ClasseA A;
  ClasseA * ponteiro = &A;
}

Something similar, returning a reference to you, is very common:

Something very similar to returning a pointer to itself is often used, as in the% of assignment operators, where you return a reference to the object itself (created by dereferencing overload ), for example: / p>

ClasseA& ClasseA::operator = (ClasseA const & outra) {
  //..(algumas operações de atribuição)..
  return *this; //semelhante a retornar ponteiro, (refere-se a este objeto)
                //mas a referência é mais transparente.
                //assim como o ponteiro, 
                //  a referência será invalidada quando o objeto for destruído
}
    
07.03.2017 / 23:37
2

Example showing the undefined behavior when using the resource used by the OP.

// arquivo ptrtest.cpp

#include <iostream>
using namespace std;

class A
{
   public:
      int x;
      A();
      A* getThis() { return this; }
};

A::A()
{
   cout << "* this=" << (void*)this << '\n';
   x = 42;
   cout << "* &A::x=" << (void*)&x << '\n';
}

int main()
{
   A* aPtr;
   aPtr = A().getThis();
   int z = 1;
   cout << "* &aPtr= " << (void*)&aPtr << '\n';
   cout << "* &z=    " << (void*)&z << '\n';
   cout << "* A::x=  " << aPtr->x << '\n';
}

Compiling the above code in gcc 6.3.1 with the command line

g++ -O3 -o ptrtest ptrtest.cpp

(Option -O3 optimizes the generated code).

When running, the result is:

* this=0x7ffdd82e7550
* &A::x=0x7ffdd82e7550
* &aPtr= 0x7ffdd82e7558
* &z=    0x7ffdd82e7550
* A::x=  1

Note that the variable A :: x was overwritten by the value of z.

Compiling without optimization:

g++ -o ptrtest ptrtest.cpp

When running, the result is now:

* this=0x7ffdd82e7550
* &A::x=0x7ffdd82e7550
* &aPtr= 0x7ffdd82e7558
* &z=    0x7ffdd82e7550
* A::x=  42

Note that the variable A :: x now was not was overwritten by the value of z.

This demonstrates that using temporary value addresses has undefined behavior . In this case, depending on the compilation options, the program has different behaviors. The effects could be more drastic, such as the program submitting exception addressing, or looping, etc., any behavior could happen (according to the language definition) because this is the behavior definition indefinidio: in principle, anything can happen.

    
09.03.2017 / 01:54
1

It depends what you do with the pointer.

The object is being created in stack , this you already know. Therefore the pointer will reference a position in stack . When this function is finished, the object ceases to exist, there can no longer be a reference to it. But the reference created there is also gone, then ok. But what if you escaped the reference to some object by throwing the pointer at it and that object survives more than this function? You will be accessing an object that no longer exists. And I do not know what's worse, making a mistake, or seeming to work in multiple scenarios, but not at all.

You would not have to use delete if you did not use new .

Now if by chance getThis() returns another object created in heap , there you have to manage it, but it does not seem to be the case.

    
07.03.2017 / 02:41