1

I have a class having an element which contains a raw pointer of another object as following. Note that the example I simplified from my actual work may probably work, but I am trying to get conceptual mistake if I am doing here, because in the perfectly same structure and scenario I am getting segmentation fault error.

    /*This doesn't have a raw pointer of another object*/
       class H1 {
         private:
          int x, y;
         public:
          constructors;
          copy_constructor;
        }
    /*This has a h1_ptr element which is a raw pointer of H1*/
       class G1 {
         private:
          int count;
          H1* h1_ptr;
         public:
          G1(int c, H1* lst){
           count = 0;
           h1_ptr = lst;
         }
         G1(const G1& g) {
           count = g.count;
           h1_ptr = g.h1_ptr;
         }
         G1& operator=(const G1& g)
         {
           count = g.count;
           h1_ptr = g.h1_ptr;
         }
        }
    /*The class that I create unique_ptr from*/
class H3 {
         private:
          H1 h1, h2;
          G1 g1;
         public:
          H3(H1 _h1, H1 _h2, G1 _g1){
             h1 = _h1; h2 = _h2; g1 = _g1;
          }
        }

I create a unique_ptr from the class H3 in a function and return it to another function:

unique_ptr<H3> create_ptr(){
      H1 h1(5, 10);
      H1 h2(50, 100);

      H1* h1_lst = new H1[20];
      H1 ls;
      for (int i=0;i<20;i++)
      {
        H1 ls(i, i*2);
        h1_lst[i] = ls;
      } 
      G1 g1(200, h1_lst);
      unique_ptr<H3> p_h3(new H3(h1, h2, g1));
      return p_h3;
    }
 int main(){
   unique_ptr<H3> p_h3 = create_ptr();
   H3* h_3 = p_h3.get();//to get the raw pointer
   G1 g1(h_3->g1);//corrected
   H1* h1_lst = g1.h1_ptr;
   for (int i=0;i< 5; i++){
     //I just want 5 of them even if there is more
     H1 ls = h1_lst[i];
     cout << ls.x << ":" << ls.y << endl;
   }
   return 0;
 }

This will just write 1 or 2 lines, then it will crash with segmentation fault. If I didn't return the unique pointer, but get the raw pointer and write the result in the create_ptr function instead, it would work perfectly fine.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
iesiyok
  • 79
  • 2
  • 10
  • The posted code won't even compile. G1 g1 = h_3->g1; will get an access violation. Any reason why you don't use std::vector? Seeing the code for the constructor and copy constructors is required to find the memory corruption. – steve Aug 23 '18 at 04:04
  • Let's put it this way: The code you are showing falls in the category "you can write C++ this way if you know what you are doing". I.e., what you show is not wrong per se. But you are hiding a lot of code behind the words `constructors` and `copy_constructors`, and the source of your problems is *very* likely there. – j6t Aug 23 '18 at 06:09
  • I edited the code based on your comments. I still get "Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) " on Xcode and segmentation fault on gcc compiler. Where do you want me to use std::vector? – iesiyok Aug 23 '18 at 08:30
  • The conceptual mistake is to use raw pointers in the first place. – n. m. could be an AI Aug 23 '18 at 09:06
  • 1
    That is unfortunately not my choice, I am using a library and those objects are coming from it. It's very complicated and not very easy to change. – iesiyok Aug 23 '18 at 09:08
  • 1
    Please post a [mcve]. – n. m. could be an AI Aug 23 '18 at 12:14

2 Answers2

0

The problem was in destructor of foreign class like (G1 in this example) which was trying to delete raw pointer objects. When I remove those delete processes it works fine, but I believe this is still a bad idea.

iesiyok
  • 79
  • 2
  • 10
-2

You cannot copy assign the std::unique_ptr from another unique pointer. Its not CopyConstructible or CopyAssignable.

However, you can transfer ownership using std::move:

std::unique_ptr iptr1{new int{1}};
std::unique_ptr iptr2 = std::move(iptr1); // iptr1 now null 

If you whish to have multiple owners of the pointer use std::shared_ptr instead.

Read more about it on the cppreference page std::unique_ptr

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
kaps
  • 186
  • 4
  • 18
  • If you mean this assignment here : unique_ptr

    p_h3 = create_ptr(); The compiler doesn't even complain about this.

    – iesiyok Aug 23 '18 at 08:31
  • 2
    You can definitily "assign" a `unique_ptr`. You cannot "CopyAssign", but you can "MoveAssign". – rubenvb Aug 23 '18 at 09:07
  • Assign as in unique_ptr<..> a= b; // where b is another unique pointer. – kaps Aug 23 '18 at 15:12