有关在python ctypes中调整大小的问题

时间:2012-07-24 15:34:35

标签: python ctypes

我找到了一个在python ctypes

中调整数组大小的答案
from ctypes import *

list = (c_int*1)()

def customresize(array, new_size):
    resize(array, sizeof(array._type_)*new_size)
    return (array._type_*new_size).from_address(addressof(array))

list[0] = 123
list = customresize(list, 5)

>>> list[0]
123
>>> list[4]
0

如果我再次打电话:

list = customresize(list, 40)

它给出错误:

ValueError: Memory cannot be resized because this object doesn't own it

为什么它仅在您第一次拨打customresize()时才有效? 我还看到了一个帖子的另一个答案:

def customresize(array, new_size):
    return (array._type_*new_size).from_address(addressof(array))

此处customresize()无论您拨打多少次都可以使用。

但它提出了另一个问题,我发现当你将list调整为更大的大小时,我的python.exe不会使用更多的内存,这意味着没有为调整大小的list分配内存。在没有分配的情况下为内存提供可访问性是非常危险的吗?为什么ctypes.resize是这样设计的?真的很困惑......

2 个答案:

答案 0 :(得分:2)

from_address很危险,因为它无法确保您已分配正在访问的内存,因此可能导致应用程序崩溃或更糟。此外,它不拥有它所指向的内存,因此如果原始所有者被删除,则内存可以被重用于其他内容。

这里的一个选择是保持对原始数组的引用:

def customresize(array, new_size):
    base = getattr(array, 'base', array)
    resize(base, sizeof(array._type_)*new_size)
    new_array = (array._type_*new_size).from_address(addressof(base))
    new_array.base = base

或者更安全,你可以从旧的数组中创建一个新的数组:

list = (c_int * 5)(*list)

答案 1 :(得分:0)

让我自己总结一下这个问题。但请注意@ecatmur和其他人 resize()函数可用于调整现有ctypes对象的内存缓冲区的大小。该函数将对象作为第一个参数,并将请求的大小(以字节为单位)作为第二个参数。但是,调整大小的对象仍然基于其原始大小限制了对内存缓冲区的访问。解决问题。定义了3种不同的功能:

def customresize1(array, new_size):
    resize(array, sizeof(array._type_)*new_size)
    return (array._type_*new_size).from_address(addressof(array))
def customresize2(array, new_size):
    return (array._type_*new_size).from_address(addressof(array))
def customresize3(array, new_size):
    base = getattr(array, 'base', array)
    resize(base, sizeof(array._type_)*new_size)
    new_array = (array._type_*new_size).from_address(addressof(base))
    new_array.base = base

所有函数都返回一个共享原始所有者内存的对象,该对象不拥有内存且无法调整大小(例如,在customresize1中出错)

customresize2会返回一个调整大小的数组,但请注意from_address不会为调整大小分配内存..

customresize3保留拥有内存的基础对象的记录,但返回的对象不是内存的所有者

因为python正在动态分配它的内存和垃圾收集,所以,如果你想调整大小,只需重做大小就行了。例如:

list = (c_int * NEW_SIZE)()

或者您可能希望保留原始值:

list = (c_int * NEW_SIZE)(*list)
相关问题