Make Object free itself on init and destruction

Will make for a *much* easier way to code.

Patches with more std::move coming on top.

Most things seem to work though i'm pretty sure some things are broken.

NEEDS TESTING
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 279f650..73c2fe6 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -2971,9 +2971,10 @@
   fontsDictObj.initDict(fontsDict);
 
   Dict *dict = new Dict(xref);
+  dict->decRef();
   dict->add(copyString("Font"), &fontsDictObj);
-
   fontResDict->initDict(dict);
+
   return GfxFont::makeFont(xref, "AnnotDrawFont", dummyRef, fontDict);
 }
 
diff --git a/poppler/Array.cc b/poppler/Array.cc
index 230c328..131e413 100644
--- a/poppler/Array.cc
+++ b/poppler/Array.cc
@@ -16,7 +16,7 @@
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
-// Copyright (C) 2013 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2013, 2017 Albert Astals Cid <aacid@kde.org>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -97,7 +97,8 @@
     }
     elems = (Object *)greallocn(elems, size, sizeof(Object));
   }
-  elems[length] = *elem;
+  elems[length].initNullNoFree();
+  elem->shallowCopy(&elems[length]);
   ++length;
 }
 
diff --git a/poppler/Array.h b/poppler/Array.h
index e78e399..6240295 100644
--- a/poppler/Array.h
+++ b/poppler/Array.h
@@ -16,6 +16,7 @@
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2017 Albert Astals Cid <aacid@kde.org>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -58,7 +59,8 @@
   // Copy array with new xref
   Object *copy(XRef *xrefA, Object *obj);
 
-  // Add an element.
+  // Add an element
+  // elem becomes a dead object after this call
   void add(Object *elem);
 
   // Remove an element by position
diff --git a/poppler/Catalog.cc b/poppler/Catalog.cc
index 0e37c84..c415c7f 100644
--- a/poppler/Catalog.cc
+++ b/poppler/Catalog.cc
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
-// Copyright (C) 2005-2013, 2015 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005-2013, 2015, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2005 Jeff Muizelaar <jrmuizel@nit.ca>
 // Copyright (C) 2005 Jonathan Blandford <jrb@redhat.com>
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg@redhat.com>
@@ -548,7 +548,10 @@
   Object obj;
 
   catalogLocker();
-  getDestNameTree()->getValue(i).fetch(xref, &obj);
+  Object *aux = getDestNameTree()->getValue(i);
+  if (aux) {
+    aux->fetch(xref, &obj);
+  }
   dest = createLinkDest(&obj);
   obj.free();
 
@@ -558,16 +561,15 @@
 FileSpec *Catalog::embeddedFile(int i)
 {
     Object efDict;
-    Object obj;
     catalogLocker();
-    obj = getEmbeddedFileNameTree()->getValue(i);
+    Object *obj = getEmbeddedFileNameTree()->getValue(i);
     FileSpec *embeddedFile = 0;
-    if (obj.isRef()) {
+    if (obj->isRef()) {
       Object fsDict;
-      embeddedFile = new FileSpec(obj.fetch(xref, &fsDict));
+      embeddedFile = new FileSpec(obj->fetch(xref, &fsDict));
       fsDict.free();
-    } else if (obj.isDict()) {
-      embeddedFile = new FileSpec(&obj);
+    } else if (obj->isDict()) {
+      embeddedFile = new FileSpec(obj);
     } else {
       Object null;
       embeddedFile = new FileSpec(&null);
@@ -581,7 +583,10 @@
   // getJSNameTree()->getValue(i) returns a shallow copy of the object so we
   // do not need to free it
   catalogLocker();
-  getJSNameTree()->getValue(i).fetch(xref, &obj);
+  Object *aux = getJSNameTree()->getValue(i);
+  if (aux) {
+    aux->fetch(xref, &obj);
+  }
 
   if (!obj.isDict()) {
     obj.free();
@@ -806,12 +811,12 @@
   }
 }
 
-Object NameTree::getValue(int index)
+Object *NameTree::getValue(int index)
 {
   if (index < length) {
-    return entries[index]->value;
+    return &entries[index]->value;
   } else {
-    return Object();
+    return nullptr;
   }
 }
 
diff --git a/poppler/Catalog.h b/poppler/Catalog.h
index 81b0e12..ed9ec75 100644
--- a/poppler/Catalog.h
+++ b/poppler/Catalog.h
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
-// Copyright (C) 2005, 2007, 2009-2011, 2013 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005, 2007, 2009-2011, 2013, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2005 Jonathan Blandford <jrb@redhat.com>
 // Copyright (C) 2005, 2006, 2008 Brad Hards <bradh@frogmouth.net>
 // Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
@@ -71,8 +71,8 @@
   void init(XRef *xref, Object *tree);
   GBool lookup(GooString *name, Object *obj);
   int numEntries() { return length; };
-  // iterator accessor, note it returns a shallow copy, do not free the object
-  Object getValue(int i);
+  // iterator accessor, note it returns a pointer to the internal object, do not free nor delete it
+  Object *getValue(int i);
   GooString *getName(int i);
 
 private:
diff --git a/poppler/DCTStream.cc b/poppler/DCTStream.cc
index bfdb0ea..6bdb003 100644
--- a/poppler/DCTStream.cc
+++ b/poppler/DCTStream.cc
@@ -5,7 +5,7 @@
 // This file is licensed under the GPLv2 or later
 //
 // Copyright 2005 Jeff Muizelaar <jeff@infidigm.net>
-// Copyright 2005-2010, 2012 Albert Astals Cid <aacid@kde.org>
+// Copyright 2005-2010, 2012, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright 2009 Ryszard Trojnacki <rysiek@menel.com>
 // Copyright 2010 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright 2011 Daiki Ueno <ueno@unixuser.org>
@@ -60,16 +60,16 @@
 {
 }
 
-DCTStream::DCTStream(Stream *strA, int colorXformA, Object *dict, int recursion) :
+DCTStream::DCTStream(Stream *strA, int colorXformA, Dict *dict, int recursion) :
   FilterStream(strA) {
   colorXform = colorXformA;
   if (dict != NULL) {
     Object obj;
 
-    dict->dictLookup("Width", &obj, recursion);
+    dict->lookup("Width", &obj, recursion);
     err.width = (obj.isInt() && obj.getInt() <= JPEG_MAX_DIMENSION) ? obj.getInt() : 0;
     obj.free();
-    dict->dictLookup("Height", &obj, recursion);
+    dict->lookup("Height", &obj, recursion);
     err.height = (obj.isInt() && obj.getInt() <= JPEG_MAX_DIMENSION) ? obj.getInt() : 0;
     obj.free();
   } else
diff --git a/poppler/DCTStream.h b/poppler/DCTStream.h
index cfa0663..00e0484 100644
--- a/poppler/DCTStream.h
+++ b/poppler/DCTStream.h
@@ -6,7 +6,7 @@
 //
 // Copyright 2005 Jeff Muizelaar <jeff@infidigm.net>
 // Copyright 2005 Martin Kretzschmar <martink@gnome.org>
-// Copyright 2005-2007, 2009-2011 Albert Astals Cid <aacid@kde.org>
+// Copyright 2005-2007, 2009-2011, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright 2010 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright 2011 Daiki Ueno <ueno@unixuser.org>
 // Copyright 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
@@ -64,7 +64,7 @@
 class DCTStream: public FilterStream {
 public:
 
-  DCTStream(Stream *strA, int colorXformA, Object *dict, int recursion);
+  DCTStream(Stream *strA, int colorXformA, Dict *dict, int recursion);
   ~DCTStream();
   StreamKind getKind() override { return strDCT; }
   void reset() override;
diff --git a/poppler/Dict.cc b/poppler/Dict.cc
index c2a94f4..cdd7d27 100644
--- a/poppler/Dict.cc
+++ b/poppler/Dict.cc
@@ -16,7 +16,7 @@
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org>
-// Copyright (C) 2008, 2010, 2013, 2014 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2008, 2010, 2013, 2014, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha@gmail.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
@@ -108,12 +108,9 @@
   dictA->xref = xrefA;
   for (int i=0; i<length; i++) {
     if (dictA->entries[i].val.getType() == objDict) {
-       Dict *dict = dictA->entries[i].val.getDict();
-       Object obj;
-       obj.initDict(dict->copy(xrefA));
-       dictA->entries[i].val.free();
-       dictA->entries[i].val = obj;
-       obj.free();
+       Dict *copy = dictA->entries[i].val.getDict()->copy(xrefA);
+       dictA->entries[i].val.initDict(copy);
+       copy->decRef();
     }
   }
   return dictA;
@@ -161,7 +158,8 @@
     entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry));
   }
   entries[length].key = key;
-  entries[length].val = *val;
+  entries[length].val.initNullNoFree();
+  val->shallowCopy(&entries[length].val);
   ++length;
 }
 
@@ -169,8 +167,8 @@
   if (!sorted && length >= SORT_LENGTH_LOWER_LIMIT)
   {
       dictLocker();
-      sorted = gTrue;
-      std::sort(entries, entries+length, cmpDictEntries);
+// TODO      sorted = gTrue;
+//       std::sort(entries, entries+length, cmpDictEntries);
   }
 
   if (sorted) {
@@ -208,7 +206,6 @@
   } else {
     int i; 
     bool found = false;
-    DictEntry tmp;
     if(length == 0) {
       return;
     }
@@ -226,9 +223,11 @@
     gfree(entries[i].key);
     entries[i].val.free();
     length -= 1;
-    tmp = entries[length];
-    if (i!=length) //don't copy the last entry if it is deleted 
-      entries[i] = tmp;
+    if (i!=length) {
+      //don't copy the last entry if it is deleted
+      entries[i].key = entries[length].key;
+      entries[length].val.shallowCopy(&entries[i].val);
+    }
   }
 }
 
@@ -242,7 +241,7 @@
   if (e) {
     dictLocker();
     e->val.free();
-    e->val = *val;
+    val->shallowCopy(&e->val);
   } else {
     add (copyString(key), val);
   }
diff --git a/poppler/Dict.h b/poppler/Dict.h
index fba99ed..c6b43e4 100644
--- a/poppler/Dict.h
+++ b/poppler/Dict.h
@@ -16,7 +16,7 @@
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 // Copyright (C) 2007-2008 Julien Rebetez <julienr@svn.gnome.org>
-// Copyright (C) 2010 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2010, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha@gmail.com>
 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 //
@@ -64,9 +64,11 @@
   int getLength() { return length; }
 
   // Add an entry.  NB: does not copy key.
+  // val becomes a dead object after the call
   void add(char *key, Object *val);
 
   // Update the value of an existing entry, otherwise create it
+  // val becomes a dead object after the call
   void set(const char *key, Object *val);
   // Remove an entry. This invalidate indexes
   void remove(const char *key);
diff --git a/poppler/Form.cc b/poppler/Form.cc
index ced3140..e4a20dd 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -689,7 +689,6 @@
   default:
     error(errSyntaxWarning, -1, "SubType on non-terminal field, invalid document?");
     numChildren--;
-    terminal = false;
   }
 }
 
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 3722028..2fa8c7d 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -817,8 +817,7 @@
 
     // got an argument - save it
     } else if (numArgs < maxArgs) {
-      args[numArgs++] = obj;
-
+      obj.shallowCopy(&args[numArgs++]);
     // too many arguments - something is wrong
     } else {
       error(errSyntaxError, getPos(), "Too many args in content stream");
@@ -4272,7 +4271,7 @@
   GBool maskInvert;
   GBool maskInterpolate;
   Stream *maskStr;
-  Object obj1, obj2;
+  Object obj1;
   int i, n;
 
   // get info from the stream
@@ -4378,12 +4377,12 @@
       dict->lookup("D", &obj1);
     }
     if (obj1.isArray()) {
+      Object obj2;
       obj1.arrayGet(0, &obj2);
       // Table 4.39 says /Decode must be [1 0] or [0 1]. Adobe
       // accepts [1.0 0.0] as well.
       if (obj2.isNum() && obj2.getNum() >= 0.9)
 	invert = gTrue;
-      obj2.free();
     } else if (!obj1.isNull()) {
       goto err2;
     }
@@ -4418,12 +4417,10 @@
       dict->lookup("CS", &obj1);
     }
     if (obj1.isName() && inlineImg) {
+      Object obj2;
       res->lookupColorSpace(obj1.getName(), &obj2);
       if (!obj2.isNull()) {
-	obj1.free();
-	obj1 = obj2;
-      } else {
-	obj2.free();
+	obj2.shallowCopy(&obj1);
       }
     }
     if (!obj1.isNull()) {
@@ -4549,12 +4546,10 @@
 	maskDict->lookup("CS", &obj1);
       }
       if (obj1.isName()) {
+	Object obj2;
 	res->lookupColorSpace(obj1.getName(), &obj2);
 	if (!obj2.isNull()) {
-	  obj1.free();
-	  obj1 = obj2;
-	} else {
-	  obj2.free();
+	  obj2.shallowCopy(&obj1);
 	}
       }
       maskColorSpace = GfxColorSpace::parse(NULL, &obj1, out, state);
@@ -4584,6 +4579,7 @@
             maskWidth, maskHeight, width, height);
         } else {
           GfxColor matteColor;
+          Object obj2;
           for (i = 0; i < colorSpace->getNComps(); i++) {
             obj1.getArray()->get(i, &obj2);
             if (!obj2.isNum()) {
@@ -4593,7 +4589,6 @@
               break;
             }
             matteColor.c[i] = dblToCol(obj2.getNum());
-            obj2.free();
           }
           if (i == colorSpace->getNComps()) {
             maskColorMap->setMatteColor(&matteColor);
@@ -4674,13 +4669,13 @@
 	maskDict->lookup("D", &obj1);
       }
       if (obj1.isArray()) {
+	Object obj2;
 	obj1.arrayGet(0, &obj2);
 	// Table 4.39 says /Decode must be [1 0] or [0 1]. Adobe
 	// accepts [1.0 0.0] as well.
 	if (obj2.isNum() && obj2.getNum() >= 0.9) {
 	  maskInvert = gTrue;
 	}
-	obj2.free();
       } else if (!obj1.isNull()) {
 	goto err2;
       }
@@ -5081,7 +5076,7 @@
   // make stream
   if (parser->getStream()) {
     str = new EmbedStream(parser->getStream(), &dict, gFalse, 0);
-    str = str->addFilters(&dict);
+    str = str->addFilters(str->getDict());
   } else {
     str = NULL;
     dict.free();
diff --git a/poppler/Movie.cc b/poppler/Movie.cc
index f68b6ad..7775eb5 100644
--- a/poppler/Movie.cc
+++ b/poppler/Movie.cc
@@ -6,7 +6,7 @@
 // Hugo Mercier <hmercier31[at]gmail.com> (c) 2008
 // Pino Toscano <pino@kde.org> (c) 2008
 // Carlos Garcia Campos <carlosgc@gnome.org> (c) 2010
-// Albert Astals Cid <aacid@kde.org> (c) 2010
+// Albert Astals Cid <aacid@kde.org> (c) 2010, 2017
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -265,6 +265,23 @@
   }
 }
 
+Movie::Movie(const Movie &other)
+{
+  ok = other.ok;
+  rotationAngle = other.rotationAngle;
+  width = other.width;
+  height = other.height;
+  showPoster = other.showPoster;
+  MA = other.MA;
+
+  other.poster.copy(&poster);
+
+  if (other.fileName)
+    fileName = other.fileName->copy();
+  else
+    fileName = nullptr;
+}
+
 void Movie::getFloatingWindowSize(int *widthA, int *heightA)
 {
   *widthA = int(width * double(MA.znum) / MA.zdenum);
@@ -272,14 +289,5 @@
 }
 
 Movie* Movie::copy() {
-
-  // call default copy constructor
-  Movie* new_movie = new Movie(*this);
-
-  if (fileName)
-    new_movie->fileName = fileName->copy();
-
-  poster.copy(&new_movie->poster);
-
-  return new_movie;
+  return new Movie(*this);
 }
diff --git a/poppler/Movie.h b/poppler/Movie.h
index 1a16265..587853e 100644
--- a/poppler/Movie.h
+++ b/poppler/Movie.h
@@ -5,6 +5,7 @@
 //---------------------------------------------------------------------------------
 // Hugo Mercier <hmercier31[at]gmail.com> (c) 2008
 // Carlos Garcia Campos <carlosgc@gnome.org> (c) 2010
+// Albert Astals Cid <aacid@kde.org> (c) 2017
 //
 // This program is free software; you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -71,6 +72,7 @@
  public:
   Movie(Object *objMovie, Object *objAct);
   Movie(Object *objMovie);
+  Movie(const Movie &movie);
   ~Movie();
 
   GBool isOk() { return ok; }
diff --git a/poppler/Object.cc b/poppler/Object.cc
index d06bb39..e84abcc 100644
--- a/poppler/Object.cc
+++ b/poppler/Object.cc
@@ -13,7 +13,7 @@
 // All changes made under the Poppler project to this file are licensed
 // under GPL version 2 or later
 //
-// Copyright (C) 2008, 2010, 2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2008, 2010, 2012, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
 // To see a description of the changes please see the Changelog file that
@@ -54,14 +54,36 @@
   "error",
   "eof",
   "none",
-  "integer64"
+  "integer64",
+  "dead"
 };
 
 #ifdef DEBUG_MEM
 int Object::numAlloc[numObjTypes] =
-  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 #endif
 
+Object::Object(Object&& other)
+{
+  type = other.type;
+  real = other.real; // this is the biggest of the union so it's enough
+  other.type = objDead;
+}
+
+Object& Object::operator=(Object&& other)
+{
+  free();
+  type = other.type;
+  real = other.real; // this is the biggest of the union so it's enough
+  other.type = objDead;
+  return *this;
+}
+
+Object::~Object()
+{
+  free();
+}
+
 Object *Object::initArray(XRef *xref) {
   initObj(objArray);
   array = new Array(xref);
@@ -87,8 +109,11 @@
   return this;
 }
 
-Object *Object::copy(Object *obj) {
-  *obj = *this;
+Object *Object::copy(Object *obj) const {
+  CHECK_NOT_DEAD;
+
+  obj->type = type;
+  obj->real = real; // this is the biggest of the union so it's enough
   switch (type) {
   case objString:
     obj->string = string->copy();
@@ -117,7 +142,20 @@
   return obj;
 }
 
+Object *Object::shallowCopy(Object *obj)
+{
+  CHECK_NOT_DEAD;
+
+  obj->free();
+  obj->type = type;
+  obj->real = real; // this is the biggest of the union so it's enough
+  type = objDead;
+  return obj;
+}
+
 Object *Object::fetch(XRef *xref, Object *obj, int recursion) {
+  CHECK_NOT_DEAD;
+
   return (type == objRef && xref) ?
          xref->fetch(ref.num, ref.gen, obj, recursion) : copy(obj);
 }
@@ -225,6 +263,9 @@
   case objNone:
     fprintf(f, "<none>");
     break;
+    case objDead:
+    fprintf(f, "<dead>");
+    break;
   case objInt64:
     fprintf(f, "%lld", int64g);
     break;
diff --git a/poppler/Object.h b/poppler/Object.h
index e3f8f37..8cda79d 100644
--- a/poppler/Object.h
+++ b/poppler/Object.h
@@ -15,7 +15,7 @@
 //
 // Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
 // Copyright (C) 2008 Kees Cook <kees@outflux.net>
-// Copyright (C) 2008, 2010 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2008, 2010, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2009 Jakub Wilk <jwilk@jwilk.net>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
@@ -65,6 +65,12 @@
         abort(); \
     }
 
+#define CHECK_NOT_DEAD \
+  if (unlikely(type == objDead)) { \
+        error(errInternal, 0, "Call to dead object"); \
+        abort(); \
+    }
+
 class XRef;
 class Array;
 class Dict;
@@ -105,19 +111,20 @@
   objNone,			// uninitialized object
 
   // poppler-only objects
-  objInt64			// integer with at least 64-bits
+  objInt64,			// integer with at least 64-bits
+  objDead			// and object after shallowCopy
 };
 
-#define numObjTypes 15		// total number of object types
+#define numObjTypes 16		// total number of object types
 
 //------------------------------------------------------------------------
 // Object
 //------------------------------------------------------------------------
 
 #ifdef DEBUG_MEM
-#define initObj(t) zeroUnion(); ++numAlloc[type = t]
+#define initObj(t) free(); zeroUnion(); ++numAlloc[type = t]
 #else
-#define initObj(t) zeroUnion(); type = t
+#define initObj(t) free(); zeroUnion(); type = t
 #endif
 
 class Object {
@@ -128,6 +135,13 @@
   // Default constructor.
   Object():
     type(objNone) { zeroUnion(); }
+  ~Object();
+
+  Object(Object&& other);
+  Object& operator=(Object&& other);
+
+  Object &operator=(const Object &other) = delete;
+  Object(const Object &other) = delete;
 
   // Initialize an object.
   Object *initBool(GBool boolnA)
@@ -142,6 +156,14 @@
     { initObj(objName); name = copyString(nameA); return this; }
   Object *initNull()
     { initObj(objNull); return this; }
+  Object *initNullNoFree()
+    {
+      type = objNull;
+#ifdef DEBUG_MEM
+#define initObj(t) ++numAlloc[objNull]
+#endif
+      return this;
+    }
   Object *initArray(XRef *xref);
   Object *initDict(XRef *xref);
   Object *initDict(Dict *dictA);
@@ -157,12 +179,11 @@
   Object *initInt64(long long int64gA)
     { initObj(objInt64); int64g = int64gA; return this; }
 
-  // Copy an object.
-  Object *copy(Object *obj);
-  Object *shallowCopy(Object *obj) {
-    *obj = *this;
-    return obj;
-  }
+  // Copy this to obj
+  Object *copy(Object *obj) const;
+
+  // Copy this to obj. This becomes a none object
+  Object *shallowCopy(Object *obj);
 
   // If object is a Ref, fetch and return the referenced object.
   // Otherwise, return a copy of the object.
@@ -172,24 +193,24 @@
   void free();
 
   // Type checking.
-  ObjType getType() { return type; }
-  GBool isBool() { return type == objBool; }
-  GBool isInt() { return type == objInt; }
-  GBool isReal() { return type == objReal; }
-  GBool isNum() { return type == objInt || type == objReal || type == objInt64; }
-  GBool isString() { return type == objString; }
-  GBool isName() { return type == objName; }
-  GBool isNull() { return type == objNull; }
-  GBool isArray() { return type == objArray; }
-  GBool isDict() { return type == objDict; }
-  GBool isStream() { return type == objStream; }
-  GBool isRef() { return type == objRef; }
-  GBool isCmd() { return type == objCmd; }
-  GBool isError() { return type == objError; }
-  GBool isEOF() { return type == objEOF; }
-  GBool isNone() { return type == objNone; }
-  GBool isInt64() { return type == objInt64; }
-  GBool isIntOrInt64() { return type == objInt || type == objInt64; }
+  ObjType getType() { CHECK_NOT_DEAD; return type; }
+  GBool isBool() { CHECK_NOT_DEAD; return type == objBool; }
+  GBool isInt() { CHECK_NOT_DEAD; return type == objInt; }
+  GBool isReal() { CHECK_NOT_DEAD; return type == objReal; }
+  GBool isNum() { CHECK_NOT_DEAD; return type == objInt || type == objReal || type == objInt64; }
+  GBool isString() { CHECK_NOT_DEAD; return type == objString; }
+  GBool isName() { CHECK_NOT_DEAD; return type == objName; }
+  GBool isNull() { CHECK_NOT_DEAD; return type == objNull; }
+  GBool isArray() { CHECK_NOT_DEAD; return type == objArray; }
+  GBool isDict() { CHECK_NOT_DEAD; return type == objDict; }
+  GBool isStream() { CHECK_NOT_DEAD; return type == objStream; }
+  GBool isRef() { CHECK_NOT_DEAD; return type == objRef; }
+  GBool isCmd() { CHECK_NOT_DEAD; return type == objCmd; }
+  GBool isError() { CHECK_NOT_DEAD; return type == objError; }
+  GBool isEOF() { CHECK_NOT_DEAD; return type == objEOF; }
+  GBool isNone() { CHECK_NOT_DEAD; return type == objNone; }
+  GBool isInt64() { CHECK_NOT_DEAD; return type == objInt64; }
+  GBool isIntOrInt64() { CHECK_NOT_DEAD; return type == objInt || type == objInt64; }
 
   // Special type checking.
   GBool isName(const char *nameA)
diff --git a/poppler/OptionalContent.cc b/poppler/OptionalContent.cc
index 44eef19..dd83970 100644
--- a/poppler/OptionalContent.cc
+++ b/poppler/OptionalContent.cc
@@ -64,7 +64,7 @@
     ocg.free();
     ocgList.arrayGetNF(i, &ocg);
     if (!ocg.isRef()) {
-      ocg.free();
+      delete thisOptionalContentGroup;
       break;
     }
     // TODO: we should create a lookup map from Ref to the OptionalContentGroup
diff --git a/poppler/Page.cc b/poppler/Page.cc
index dca52e4..cf687c0 100644
--- a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -15,7 +15,7 @@
 //
 // Copyright (C) 2005 Kristian Høgsberg <krh@redhat.com>
 // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
-// Copyright (C) 2005-2013, 2016 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2005-2013, 2016, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2006-2008 Pino Toscano <pino@kde.org>
 // Copyright (C) 2006 Nickolay V. Shmyrev <nshmyrev@yandex.ru>
 // Copyright (C) 2006 Scott Turner <scotty1024@mac.com>
@@ -393,7 +393,7 @@
   pageDict->lookupNF("AA", &actions);
   pageDict->lookup("Resources", &obj1);
   if (obj1.isDict()) {
-    attrs->replaceResource(obj1);
+    attrs->replaceResource(&obj1);
   }
   obj1.free();
   delete pageDict;
diff --git a/poppler/Page.h b/poppler/Page.h
index 2aaabae..7a20b55 100644
--- a/poppler/Page.h
+++ b/poppler/Page.h
@@ -20,7 +20,7 @@
 // Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
 // Copyright (C) 2008 Iñigo Martínez <inigomartinez@gmail.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
-// Copyright (C) 2012 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2012, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 //
@@ -107,8 +107,8 @@
 	? separationInfo.getDict() : (Dict *)NULL; }
   Dict *getResourceDict()
     { return resources.isDict() ? resources.getDict() : (Dict *)NULL; }
-  void replaceResource(Object obj1) 
-  {  resources.free(); obj1.copy(&resources); }
+  void replaceResource(Object *obj1)
+  {  obj1->shallowCopy(&resources); }
 
   // Clip all other boxes to the MediaBox.
   void clipBoxes();
diff --git a/poppler/Parser.cc b/poppler/Parser.cc
index 28a5460..1be2e9f 100644
--- a/poppler/Parser.cc
+++ b/poppler/Parser.cc
@@ -13,7 +13,7 @@
 // All changes made under the Poppler project to this file are licensed
 // under GPL version 2 or later
 //
-// Copyright (C) 2006, 2009, 201, 2010, 2013, 2014 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2006, 2009, 201, 2010, 2013, 2014, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 // Copyright (C) 2009 Ilya Gorenbein <igorenbein@finjan.com>
 // Copyright (C) 2012 Hib Eris <hib@hiberis.nl>
@@ -274,7 +274,7 @@
   }
 
   // get filters
-  str = str->addFilters(dict, recursion);
+  str = str->addFilters(str->getDict(), recursion);
 
   return str;
 }
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index 4a9babe..cb91ca5 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
-// Copyright (C) 2006-2010, 2012-2014, 2016 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2006-2010, 2012-2014, 2016, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2007 Krzysztof Kowalczyk <kkowalczyk@gmail.com>
 // Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
@@ -168,22 +168,22 @@
   return new GooString();
 }
 
-Stream *Stream::addFilters(Object *dict, int recursion) {
+Stream *Stream::addFilters(Dict *dict, int recursion) {
   Object obj, obj2;
   Object params, params2;
   Stream *str;
   int i;
 
   str = this;
-  dict->dictLookup("Filter", &obj, recursion);
+  dict->lookup("Filter", &obj, recursion);
   if (obj.isNull()) {
     obj.free();
-    dict->dictLookup("F", &obj, recursion);
+    dict->lookup("F", &obj, recursion);
   }
-  dict->dictLookup("DecodeParms", &params, recursion);
+  dict->lookup("DecodeParms", &params, recursion);
   if (params.isNull()) {
     params.free();
-    dict->dictLookup("DP", &params, recursion);
+    dict->lookup("DP", &params, recursion);
   }
   if (obj.isName()) {
     str = makeFilter(obj.getName(), str, &params, recursion, dict);
@@ -212,7 +212,7 @@
   return str;
 }
 
-Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursion, Object *dict) {
+Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursion, Dict *dict) {
   int pred;			// parameters
   int colors;
   int bits;
@@ -417,7 +417,7 @@
 //------------------------------------------------------------------------
 
 BaseStream::BaseStream(Object *dictA, Goffset lengthA) {
-  dict = *dictA;
+  dictA->shallowCopy(&dict);
   length = lengthA;
 }
 
@@ -788,7 +788,11 @@
 }
 
 BaseStream *FileStream::copy() {
-  return new FileStream(file, start, limited, length, &dict);
+  Object dictRef;
+  if (dict.isDict()) {
+    dictRef.initDict(dict.getDict());
+  }
+  return new FileStream(file, start, limited, length, &dictRef);
 }
 
 Stream *FileStream::makeSubStream(Goffset startA, GBool limitedA,
@@ -882,8 +886,13 @@
 }
 
 BaseStream *CachedFileStream::copy() {
+  Object dictRef;
+  if (dict.isDict()) {
+    dictRef.initDict(dict.getDict());
+  }
+
   cc->incRefCnt();
-  return new CachedFileStream(cc, start, limited, length, &dict);
+  return new CachedFileStream(cc, start, limited, length, &dictRef);
 }
 
 Stream *CachedFileStream::makeSubStream(Goffset startA, GBool limitedA,
@@ -982,7 +991,12 @@
 }
 
 BaseStream *MemStream::copy() {
-  return new MemStream(buf, start, length, &dict);
+  Object dictRef;
+  if (dict.isDict()) {
+    dictRef.initDict(dict.getDict());
+  }
+
+  return new MemStream(buf, start, length, &dictRef);
 }
 
 Stream *MemStream::makeSubStream(Goffset startA, GBool limited,
diff --git a/poppler/Stream.h b/poppler/Stream.h
index 91b524f..740f0fc 100644
--- a/poppler/Stream.h
+++ b/poppler/Stream.h
@@ -15,7 +15,7 @@
 //
 // Copyright (C) 2005 Jeff Muizelaar <jeff@infidigm.net>
 // Copyright (C) 2008 Julien Rebetez <julien@fhtagn.net>
-// Copyright (C) 2008, 2010, 2011, 2016 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2008, 2010, 2011, 2016, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
 // Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
 // Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
@@ -226,13 +226,13 @@
 
   // Add filters to this stream according to the parameters in <dict>.
   // Returns the new stream.
-  Stream *addFilters(Object *dict, int recursion = 0);
+  Stream *addFilters(Dict *dict, int recursion = 0);
 
 private:
   virtual GBool hasGetChars() { return false; }
   virtual int getChars(int nChars, Guchar *buffer);
 
-  Stream *makeFilter(char *name, Stream *str, Object *params, int recursion = 0, Object *dict = NULL);
+  Stream *makeFilter(char *name, Stream *str, Object *params, int recursion = 0, Dict *dict = nullptr);
 
   int ref;			// reference count
 #if MULTITHREADED
@@ -868,7 +868,7 @@
 class DCTStream: public FilterStream {
 public:
 
-  DCTStream(Stream *strA, int colorXformA, Object *dict, int recursion);
+  DCTStream(Stream *strA, int colorXformA, Dict *dict, int recursion);
   virtual ~DCTStream();
   virtual StreamKind getKind() { return strDCT; }
   virtual void reset();
diff --git a/poppler/StructElement.cc b/poppler/StructElement.cc
index c668820..0138ad9 100644
--- a/poppler/StructElement.cc
+++ b/poppler/StructElement.cc
@@ -6,7 +6,7 @@
 //
 // Copyright 2013, 2014 Igalia S.L.
 // Copyright 2014 Luigi Scarso <luigi.scarso@gmail.com>
-// Copyright 2014 Albert Astals Cid <aacid@kde.org>
+// Copyright 2014, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright 2015 Dmytro Morgun <lztoad@gmail.com>
 //
 //========================================================================
@@ -1256,9 +1256,7 @@
     mcidObj.free();
 
     if (childObj->dictLookupNF("Pg", &pageRefObj)->isRef()) {
-      child->pageRef = pageRefObj;
-    } else {
-      pageRefObj.free();
+      pageRefObj.shallowCopy(&child->pageRef);
     }
   } else if (childObj->isDict("OBJR")) {
     Object refObj;
@@ -1269,9 +1267,7 @@
       child = new StructElement(refObj.getRef(), treeRoot, this);
 
       if (childObj->dictLookupNF("Pg", &pageRefObj)->isRef()) {
-        child->pageRef = pageRefObj;
-      } else {
-        pageRefObj.free();
+        pageRefObj.shallowCopy(&child->pageRef);
       }
     } else {
       error(errSyntaxError, -1, "Obj object is wrong type ({0:s})", refObj.getTypeName());
diff --git a/poppler/XRef.cc b/poppler/XRef.cc
index 6ea0fbb..854f61f 100644
--- a/poppler/XRef.cc
+++ b/poppler/XRef.cc
@@ -495,7 +495,7 @@
     for (int i = size; i < newSize; ++i) {
       entries[i].offset = -1;
       entries[i].type = xrefEntryNone;
-      entries[i].obj.initNull ();
+      entries[i].obj.initNullNoFree ();
       entries[i].flags = 0;
       entries[i].gen = 0;
     }
@@ -625,7 +625,6 @@
 	goto err1;
       }
       entry.gen = obj.getInt();
-      entry.obj.initNull ();
       entry.flags = 0;
       obj.free();
       parser->getObj(&obj, gTrue);
@@ -638,7 +637,12 @@
       }
       obj.free();
       if (entries[i].offset == -1) {
-	entries[i] = entry;
+	entries[i].offset = entry.offset;
+	entries[i].gen = entry.gen;
+	entries[i].type = entry.type;
+	entries[i].flags = entry.flags;
+	entries[i].obj.initNull();
+
 	// PDF files of patents from the IBM Intellectual Property
 	// Network have a bug: the xref table claims to start at 1
 	// instead of 0.
@@ -646,7 +650,12 @@
 	    entries[1].offset == 0 && entries[1].gen == 65535 &&
 	    entries[1].type == xrefEntryFree) {
 	  i = first = 0;
-	  entries[0] = entries[1];
+	  entries[0].offset = 0;
+	  entries[0].gen = 65535;
+	  entries[0].type = xrefEntryFree;
+	  entries[0].flags = entries[1].flags;
+	  entries[1].obj.shallowCopy(&entries[0].obj);
+
 	  entries[1].offset = -1;
 	}
       }
@@ -1605,7 +1614,7 @@
 
   Object obj;
   obj.initNull();
-  Parser parser = Parser(NULL, new Lexer(NULL,
+  Parser parser(NULL, new Lexer(NULL,
      str->makeSubStream(offset, gFalse, 20, &obj)), gTrue);
 
   Object obj1, obj2, obj3;
diff --git a/utils/pdfunite.cc b/utils/pdfunite.cc
index dfe48bf..b1f2be8 100644
--- a/utils/pdfunite.cc
+++ b/utils/pdfunite.cc
@@ -7,7 +7,7 @@
 // Copyright (C) 2011-2015, 2017 Thomas Freitag <Thomas.Freitag@alfa.de>
 // Copyright (C) 2012 Arseny Solokha <asolokha@gmx.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
-// Copyright (C) 2012, 2014 Albert Astals Cid <aacid@kde.org>
+// Copyright (C) 2012, 2014, 2017 Albert Astals Cid <aacid@kde.org>
 // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
 // Copyright (C) 2013 Hib Eris <hib@hiberis.nl>
 // Copyright (C) 2015 Arthur Stavisky <vovodroid@gmail.com>
@@ -370,7 +370,7 @@
         pageDict->set("Resources", newResource);
         delete newResource;
       }
-      pages.push_back(page);
+      pages.push_back(std::move(page));
       offsets.push_back(numOffset);
       docs[i]->markPageObjects(pageDict, yRef, countRef, numOffset, refPage->num, refPage->num);
       Object annotsObj;