Project

General

Profile

Actions

Feature #21963

open

A solution to completely avoid allocated-but-uninitialized objects

Feature #21963: A solution to completely avoid allocated-but-uninitialized objects

Added by Eregon (Benoit Daloze) 1 day ago. Updated about 11 hours ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:125117]

Description

A common issue when defining a class is to handle allocated-but-uninitialized objects.
For example:

obj = MyClass.allocate
obj.some_method

This can easily segfault for classes defined in C and raise an unclear exception for classes defined in Ruby.
As a workaround many core (and non-core) classes add a check that they are initialized in every instance method.
This is suboptimal for performance and correctness, classes should not need to care about allocated-but-uninitialized objects.

Fundamentally, to solve this we need to guarantee that after the allocation function is used that either initialize, initialize_dup or initialize_clone is called.
And we can't guarantee that for Class#allocate.

The current workarounds are:

  • undef allocate, but this does not prevent Class.instance_method(:allocate).bind_call(Foo).
  • rb_undef_alloc_func() but this breaks dup, clone and Marshal.

The idea is to have in addition of the public alloc function (in rb_classext_struct.as.class.allocator) an internal alloc function.
Then:

  • Class#new, dup, clone and Marshal always use the internal alloc function, because they guarantee to call initialize, initialize_dup or initialize_clone.
  • rb_define_alloc_func() sets both fields.
  • rb_undef_alloc_func() sets both fields.
  • rb_get_alloc_func() reads the public alloc function (unchanged)
  • Class#allocate uses the public alloc function (unchanged)

We add a new method on Class, for example Class#safe_initialization, which:

  • Sets the public alloc function to UNDEF_ALLOC_FUNC, same as rb_undef_alloc_func(), so Class#allocate and rb_get_alloc_func() will raise if they are used (as they are unsafe).
  • Preserves the internal alloc function so Class#new, dup, clone and Marshal keep working.

After that the class has fully safe intialization and does not need to worry about allocated-but-uninitialized objects anymore.

From https://bugs.ruby-lang.org/issues/21852#note-7


Related issues 2 (1 open1 closed)

Related to Ruby - Feature #21852: New improved allocator function interfaceOpenActions
Related to Ruby - Bug #21267: respond_to check in Class#allocate is inconsistentClosedActions
Actions

Also available in: PDF Atom