本文介绍了出口的32位枚举时加速Python的1.48失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

执行升压Python支持新版本从C ++导出完整的32位枚举?我使用的1.48和我能够输出高达30位,但它每次都失败,因为访问冲突阅读位置是0x00000001当我尝试导出一个32位的数字。钻研enum.cpp文件,它似乎在创建对象x时,它设置字节20到1导致的失败时,它稍后尝试减小对 - >存在之前的名称。难道我只是需要升级到升压蟒蛇的新版本或只是无法导出一个完整的32位数字?感谢您的输入!

Do newer versions of Boost Python support exporting full 32 bit enumerations from C++? I am using 1.48 and am able to export up to 30 bits but it fails every time due to "Access violation reading location 0x00000001" when I try and export a 32 bit number. Delving into the enum.cpp file, it appears that when object x is created, it sets byte 20 to 1 which causes the failure when it later tries to decrement p->name before it exists. Do I just need to upgrade to a newer version of boost python or is it just not possible to export a full 32 bit number? Thanks for your input!

推荐答案

修改:由跳跳虎在工作中发现,记录在这里为后人:

EDIT: Found by Tigger at work, documenting here for posterity:

问题是在enum_object结构的定义。底层的数字存储在base_object还允许为15位数字(如短路)或30位数字(为int)粒度,但base_object只包含2个或者15位数字或1个30位的数字足够的空间。当存储在> 30位枚举值的编码要求要么3短裤或2整数根据编制的格式。其结果是,该名称构件占据所需的额外的数字存储的空间。因为该值被放置到地方名成员预计将在参考递减失败。

Problem is in the definition of the enum_object struct. The underlying digit storage in base_object allows for either 15-bit digit (as shorts) or 30-bit digit (as int) granularity, but the base_object only contains enough space for either 2x 15-bit digits or 1x 30-bit digits. When a > 30-bit enumeration value is stored the encoding requires either 3 shorts or 2 ints depending on the format compiled. The result is that the name member occupies the space needed for the extra digit storage. The reference decrement fails because the value is laid into place where the name member expects to be.

解决方案是增加的至少的名成员之前填充的32位处理32位枚举值。如果64位枚举需要一个有点遥远的未来,那么2垫的话应予以补充。

Solution is to add at least 32-bits of padding before the name member to handle 32-bit enumeration values. If 64-bit enumerations are required in a somewhat distant future then 2 pad words should be added.

struct enum_object
{
#if PY_VERSION_HEX >= 0x03000000
   PyLongObject base_object;
#else
   PyIntObject base_object;
#endif
   // ADD PADDING HERE TO FIX ALIGNMENT ISSUE
   PyObject* name;
};

END修改

TL / DR:根误差或者是在转换或通过enum_base :: add_value函数的堆栈变量假定对象对准,但它可能只是最简单的步骤,通过转换器,以查看是否该值是错位某种程度上来说。其他的实验我会尝试是交换.value的调用的顺序(即可能有助于确定是否存在一个堆栈相关的问题)。

TL/DR: The root error is either in the conversion or the assumed object alignment through a stack variable of the enum_base::add_value function, but it is probably just easiest to step through the converter to see if the value is mangled in some way. The other experiment I would try is to swap the order of the .value invocations (that might help determine if there is a stack-related issue).

详细信息:enum_base :: add_value功能是1.48和1.58之间不变(最新的)。此外,显式转换(*此)(值),基于Python API :: ::对象类和object_base_initializer模板也似乎是不变的。我没有进一步遍历的object_base构造函数来看看是否有什么改变那里。我建议加强通过与错误的值转换序列,看看是否有什么异常与上双位(我不知道你会不会有发现什么,但值得一试)发生。

Details: The enum_base::add_value function is unchanged between 1.48 and 1.58 (latest). Further, explicit conversion "(*this)(value)", based on python::api::object class and the object_base_initializer template also appears to be unchanged. I did not traverse further through the object_base constructor to see if anything changed there; I suggest stepping through the conversion sequence with the offending value to see if anything unusual occurs with the upper two-bits (I am not sure you will find anything there, but worth checking).

记住,换算值被复制到堆栈对象x =(将此)(值);并且低垂为enum_object 的p被覆盖的物体比()(即,m_ptr构件)在x.ptr引用的对象大。我不知道在这一点上,如果m_ptr是栈或堆(没有遍历这些细节),但无论哪种方式如果P是现在P-覆盖陈旧或未初始化内存则引用减量>如果没有名称将失败指向有效的内存(如你发现)。

Remember that the converted value is then copied to the stack "object x = (this)(value);" and that the downcast for enum_object p is overlaying an object that is larger than the object referenced at x.ptr() (i.e., m_ptr member). I am not sure at this point if the m_ptr is stack or heap (didn't traverse those details), but either way if p is now overlaying stale or uninitialized memory then the reference decrement at p->name will fail if it does not point to valid memory (as you found).

我不知道,如果在p>名称引用递减是必要的(对象生命周期是当地的)......我不得不想起一些了。我们可以讨论更多的在星期一......这是一个周末......休息(我应该说话!)

I am not sure if the p->name reference decrement is necessary (the object lifetime is local)... I'll have to think on that some more. We can discuss more on Monday... it's a weekend... take a break (like I should talk!)

void enum_base::add_value(char const* name_, long value)
{
    // Convert name to Python string
    object name(name_);

    // Create a new enum instance by calling the class with a value
    object x = (*this)(value);

    // Store the object in the enum class
    (*this).attr(name_) = x;

    dict d = extract<dict>(this->attr("values"))();
    d[value] = x;

    // Set the name field in the new enum instanec
    enum_object* p = downcast<enum_object>(x.ptr());
    Py_XDECREF(p->name);
    p->name = incref(name.ptr());

    dict names_dict = extract<dict>(this->attr("names"))();
    names_dict[x.attr("name")] = x;
}

这篇关于出口的32位枚举时加速Python的1.48失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-28 16:07