Skip to content

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

expect_true(before == 0);
// 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!

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

// `protect_`, which we need to manage on our own. `rhs` persists after this call, so we
// don't clear anything.
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

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_;


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


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)

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
@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