如果用户使用Rice重新定义Ruby中的initialize(),则避免使用C++代码中的Segfault

Lyk*_*kos 6 c++ ruby

我在为Ruby编写C++扩展时遇到的一个问题是,即使用户做了愚蠢的事情,也要确保它真正安全.他应该获得例外,但绝不会是SegFault.具体问题如下:我的C++类有一个非平凡的构造函数.然后我使用Rice API来包装我的C++类.如果用户在他的Ruby代码中重新定义了initialize(),则会覆盖Rice创建的initialize()函数,并且既不分配也不初始化该对象.一个玩具示例可能如下:

class Person {
public:
  Person(const string& name): m_name (name) {}
  const string& name() const { return m_name; }
private:
  string m_name;
}
Run Code Online (Sandbox Code Playgroud)

然后我像这样创建Ruby类:

define_class<Person>("Person")
  .define_constructor(Constructor<Person, const string&>(), Arg("name"))
  .define_method("name", &Person::name);
Run Code Online (Sandbox Code Playgroud)

然后,以下Ruby代码会导致Segfault

require 'MyExtension'
class Person
  def initialize
  end
end
p = Person.new
puts p.name
Run Code Online (Sandbox Code Playgroud)

我会很高兴有两种可能:禁止以某种方式覆盖Ruby中的初始化函数或检入C++,如果Object已正确分配,如果没有,则抛出异常.

我曾经直接使用Ruby C API然后很容易.我刚刚在allocate()函数和initialize方法中分配了一个由Null指针和一个设置为false的标志组成的虚拟对象,我分配了真实对象并将标志设置为true.在每个方法中,我检查了该标志并引发异常,如果它是假的.但是,我用Ruby C API编写了许多愚蠢的重复代码,我首先必须包装我的C++类,以便它们可以从C访问,然后包装和解包Ruby类型等,另外我必须检查这个愚蠢的标志每一种方法,所以我迁移到赖斯,这真的很好,我很高兴.

但是,在Rice中,程序员只能提供一个在rice创建的initialize()函数中调用的构造函数,而allocate()函数是预定义的,什么都不做.我不认为有一种简单的方法可以改变这个或以"官方"方式提供自己的分配功能.当然,我仍然可以使用C API来定义分配函数,所以我试图以某种方式混合C API和Rice,但后来我真的很讨厌,我得到了奇怪的SegFaults并且它真的很难看,所以我放弃了这个想法.

这里有没有人有赖斯的经验,或者有谁知道如何安全吗?

Lyk*_*kos 0

我现在认为这是莱斯库的问题。如果您按照记录的方式使用 Rice,您会遇到这些问题,并且没有明显的方法来解决它,并且所有解决方法都有缺点并且很糟糕。所以我想解决方案是分叉 Rice 并修复这个问题,因为他们似乎忽略了错误报告。