Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop double protecting writable vectors #365

Merged
merged 10 commits into from
Aug 8, 2024

Conversation

DavisVaughan
Copy link
Member

@DavisVaughan DavisVaughan commented Jul 27, 2024

No description provided.

Comment on lines -236 to +240
expect_true(w.is_altrep() == z.is_altrep());
// Shallow duplication of objects of a very small size (like 1:5) don't result in
// a new ALTREP object. Make sure we check ALTREP-ness of the newly duplicated object,
// instead of just blindly inheriting the ALTREP-ness of the thing we duplicate.
expect_true(w.is_altrep() != z.is_altrep());
expect_true(w.is_altrep() == ALTREP(w.data()));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found a bug here that resulted from us blindly copying over the is_altrep_ field after performing a Rf_shallow_duplicate(), which can get rid of ALTREP-ness

// TODO: This should be 1 but writable vectors are being double protected
expect_true(after - before == 2);
expect_true(after - before == 1);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay!

@@ -84,7 +84,6 @@ template <>
inline r_vector<double>::r_vector(std::initializer_list<named_arg> il)
: cpp11::r_vector<double>(safe[Rf_allocVector](REALSXP, il.size())),
capacity_(il.size()) {
protect_ = detail::store::insert(data_);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In all the specialization files, this was updating the writable protect_, which no longer exists

r_vector(const r_vector& rhs) {
SEXP old_protect = protect_;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a constructor, so protect_ starts out as R_NilValue. Nothing to do here, no need to try and release

@@ -214,8 +261,6 @@ using has_begin_fun = std::decay<decltype(*begin(std::declval<T>()))>;
template <typename T>
class r_vector : public cpp11::r_vector<T> {
private:
SEXP protect_ = R_NilValue;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the important swap of this for using cpp11::r_vector<T>::protect_;

@@ -224,6 +269,9 @@ class r_vector : public cpp11::r_vector<T> {
using cpp11::r_vector<T>::data_p_;
using cpp11::r_vector<T>::is_altrep_;
using cpp11::r_vector<T>::length_;
using cpp11::r_vector<T>::protect_;

using cpp11::r_vector<T>::get_p;

R_xlen_t capacity_ = 0;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now the only "new" field that writable vectors introduce

@@ -302,8 +350,6 @@ class r_vector : public cpp11::r_vector<T> {

explicit r_vector(const R_xlen_t size);

~r_vector();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer need a destructor, which was just freeing the writable version of protect_.

The read only parent destructor is going to be called to free its version of protect_ (which is now the only one)

inst/include/cpp11/r_vector.hpp Outdated Show resolved Hide resolved
template <typename T>
inline r_vector<T>& r_vector<T>::operator=(const r_vector<T>& rhs) {
if (data_ == rhs.data_) {
return *this;
}

cpp11::r_vector<T>::operator=(rhs);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a big part of where the double protection was accidentally coming into play before

@DavisVaughan DavisVaughan merged commit df18ba2 into r-lib:main Aug 8, 2024
14 checks passed
@DavisVaughan DavisVaughan deleted the fix/memory-leak branch August 8, 2024 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant