From 30cbbc7b0ff3566908413930b641ae9278c9a841 Mon Sep 17 00:00:00 2001 From: Filipe Maia Date: Wed, 8 Jul 2015 18:17:37 +0200 Subject: [PATCH 1/3] Fix double free issue. --- include/af/index.h | 20 ++++++++++++++++++++ src/api/cpp/index.cpp | 14 ++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/af/index.h b/include/af/index.h index 295739077e..7d0763b928 100644 --- a/include/af/index.h +++ b/include/af/index.h @@ -103,6 +103,15 @@ class AFAPI index { /// index(const af::array& idx0); + /// + /// \brief Copy constructor + /// + /// \param[in] idx0 is index to copy. + /// + /// \sa indexing + /// + index(const index& idx0); + /// /// \brief Returns true if the \ref af::index represents a af::span object /// @@ -116,6 +125,17 @@ class AFAPI index { /// \returns the af_index_t represented by this object /// const af_index_t& get() const; + + /// + /// \brief Assigns idx0 to this index + /// + /// \param[in] idx0 is the index to be assigned to the /ref af::index + /// \returns the reference to this + /// + /// + index & operator=(const index& idx0); + + }; /// diff --git a/src/api/cpp/index.cpp b/src/api/cpp/index.cpp index 2b66dd62c1..afaa716821 100644 --- a/src/api/cpp/index.cpp +++ b/src/api/cpp/index.cpp @@ -75,11 +75,25 @@ index::index(const af::array& idx0) { impl.isBatch = false; } +index::index(const af::index& idx0) { + *this = idx0; +} + index::~index() { if (!impl.isSeq) af_release_array(impl.idx.arr); } +index & index::operator=(const index& idx0) { + impl = idx0.get(); + if(impl.isSeq == false){ + // increment reference count to avoid double free + // when/if idx0 is destroyed + AF_THROW(af_retain_array(&impl.idx.arr, impl.idx.arr)); + } + return *this; +} + static bool operator==(const af_seq& lhs, const af_seq& rhs) { return lhs.begin == rhs.begin && lhs.end == rhs.end && lhs.step == rhs.step; From 9cbc641934566f3cee24e5c4d4e4f5b2d42c34a6 Mon Sep 17 00:00:00 2001 From: Filipe Maia Date: Wed, 8 Jul 2015 21:34:47 +0200 Subject: [PATCH 2/3] Add test for index copy assignment. --- test/index.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/index.cpp b/test/index.cpp index 9f23ae5fe3..28b57459fc 100644 --- a/test/index.cpp +++ b/test/index.cpp @@ -1251,3 +1251,13 @@ TEST(Indexing, SNIPPET_indexing_ref) //! [ex_indexing_ref] //TODO: Confirm the outputs are correct. see #697 } + +TEST(Indexing, SNIPPET_indexing_copy) +{ + af::array A = af::constant(0,1, s32); + af::index s1; + s1 = af::index(A); + // At exit both A and s1 will be destroyed + // but the underlying array should only be + // freed once. +} From 4d23d4136dad5063f53d7df09a0086e8f492f9eb Mon Sep 17 00:00:00 2001 From: Filipe Maia Date: Thu, 9 Jul 2015 00:27:02 +0200 Subject: [PATCH 3/3] Add move constructor and move assignment op --- include/af/index.h | 16 +++++++++++++++- src/api/cpp/index.cpp | 11 +++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/af/index.h b/include/af/index.h index 7d0763b928..373804dc17 100644 --- a/include/af/index.h +++ b/include/af/index.h @@ -135,7 +135,21 @@ class AFAPI index { /// index & operator=(const index& idx0); - +#if __cplusplus > 199711L + /// + /// \brief Move constructor + /// + /// \param[in] idx0 is index to copy. + /// + index(index &&idx0); + /// + /// \brief Move assignment operator + /// + /// \param[in] idx0 is the index to be assigned to the /ref af::index + /// \returns a reference to this + /// + index& operator=(index &&idx0); +#endif }; /// diff --git a/src/api/cpp/index.cpp b/src/api/cpp/index.cpp index afaa716821..ccc698bc3c 100644 --- a/src/api/cpp/index.cpp +++ b/src/api/cpp/index.cpp @@ -94,6 +94,17 @@ index & index::operator=(const index& idx0) { return *this; } +#if __cplusplus > 199711L +index::index(index &&idx0) { + impl = idx0.impl; +} + +index& index::operator=(index &&idx0) { + impl = idx0.impl; + return *this; +} +#endif + static bool operator==(const af_seq& lhs, const af_seq& rhs) { return lhs.begin == rhs.begin && lhs.end == rhs.end && lhs.step == rhs.step;