CXXFLAGS += -O2
endif
-FILES := test.cc zcpointer.cc
+FILES := test.cc test_helpers.cc zcpointer.cc
-DEPS := $(FILES) zcpointer.h Makefile
+DEPS := $(FILES) zcpointer.h test_helpers.h Makefile
all: test-zc test-tr
references. The goal is to allow C++ developers to write programs without _ever_ having a pointer
that is not automatically managed by a smart scoper.
-The library provides two types to do this:
+The library provides three types to do this:
- `zc::owned<T>` provides an identical interface to `std::unique_ptr<T>`, but which can track outstanding
weak references.
- `zc::ref<T>` is the return value of `zc::owned<T>::get()`. It stands for a `T*` but is used to
ensure use-after-free does not occur.
+- `zc::member<T>` is used to wrap member or local variables that should be constructed in-place, but
+ which may have pointers-to vended out to other objects. This overloads `zc::member<T>::operator&`
+ to return a `zc::ref<T>` when taking the address.
To achieve zero-cost, the zcpointer library can be compiled with or without the
`ZCPOINTER_TRACK_REFS` option. When disabled, `zc::owned` is just a type alias for `std::unique_ptr`
#include <stdexcept>
#include <vector>
+#include "test_helpers.h"
#include "zcpointer.h"
-class C {
- public:
- ~C() {}
-
- void DoThing() {}
-};
-
class TestFailure : public std::logic_error {
public:
using std::logic_error::logic_error;
EXPECT_UAF(ref->DoThing());
}
+void TestStack() {
+ zc::ref<C> rc;
+ {
+ zc::member<C> c;
+ rc = &c;
+ EXPECT(rc == &c);
+ c->DoThing();
+ }
+ EXPECT_UAF(rc->DoThing());
+}
+
+void TestMember() {
+ zc::ref<C> ref;
+ zc::ref<std::vector<C>> vec_ref;
+ {
+ X x("hello world");
+ ref = x.c();
+ vec_ref = x.vec_c();
+
+ vec_ref->push_back(C());
+ vec_ref->push_back(C());
+
+ vec_ref->at(1).DoThing();
+ }
+ EXPECT_UAF(ref->DoThing());
+ EXPECT_UAF(vec_ref->at(1).DoThing());
+}
+
#define TEST_FUNC(fn) { #fn , Test##fn }
int main() {
TEST_FUNC(Equality),
TEST_FUNC(Nulls),
TEST_FUNC(Vector),
+ TEST_FUNC(Stack),
+ TEST_FUNC(Member),
};
bool passed = true;
--- /dev/null
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "test_helpers.h"
+
+C::C() {}
+
+C::~C() {}
+
+void C::DoThing() {}
+
+X::X(const char* v) : foo_(v) {}
+
+X::~X() {}
+
+size_t X::GetCount() const {
+ return vec_c_->size();
+}
+
+std::string X::DoString() {
+ vec_c_->push_back(C());
+ return foo_;
+}
--- /dev/null
+// Copyright 2016 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ZCPOINTER_TEST_HELPERS_H_
+#define ZCPOINTER_TEST_HELPERS_H_
+
+#include <string>
+#include <vector>
+
+#include "zcpointer.h"
+
+class C {
+ public:
+ C();
+ ~C();
+ void DoThing();
+};
+
+class X {
+ public:
+ X(const char* v);
+ ~X();
+
+ zc::ref<C> c() { return &c_; }
+
+ zc::ref<std::vector<C>> vec_c() { return &vec_c_; }
+
+ size_t GetCount() const;
+
+ std::string DoString();
+
+ private:
+ std::string foo_;
+ zc::member<C> c_;
+ zc::member<std::vector<C>> vec_c_;
+};
+
+#endif // ZCPOINTER_TEST_HELPERS_H_
// See the License for the specific language governing permissions and
// limitations under the License.
+#ifndef ZCPOINTER_ZCPOINTER_H_
+#define ZCPOINTER_ZCPOINTER_H_
+
#include <limits>
#include <memory>
#include <forward_list>
#include <stdexcept>
+#include <utility>
namespace zc {
owned<T>* ptr_;
};
+template <typename T>
+class member {
+ public:
+ template <typename... Args>
+ explicit member(Args&&... args)
+ : t_(new T(std::forward<Args>(args)...)) {
+ }
+
+ ref<T> operator&() {
+ return t_.get();
+ }
+
+ T* operator->() {
+ return t_.operator->();
+ }
+
+ const T* operator->() const {
+ return t_.operator->();
+ }
+
+ private:
+ owned<T> t_;
+};
+
#else
template <typename T>
template <typename T>
using ref = T*;
+template <typename T>
+class member : public T {
+ public:
+ using T::T;
+
+ T* operator->() {
+ return this;
+ }
+
+ const T* operator->() const {
+ return this;
+ }
+};
+
#endif
} // namespace zc
+
+#endif // ZCPOINTER_ZCPOINTER_H_