1

我正在开发一个 Python C 扩展模块(用于 CPython 2.5)。它调用一些填充缓冲区的底层网络 API。

目前代码基本编写如下:

PyObject * buffer;
char * cbuf;
size_t buffer_size = 1024;
int sz;
buffer = PyString_FromStringAndSize(NULL, buffer_size);
if (buffer == NULL) return NULL;
cbuf = PyString_AsString(buffer);
Py_BEGIN_ALLOW_THREADS
sz = read(cbuf, buffer_size);
Py_END_ALLOW_THREADS
if (sz > 0 &&  sz != buffer_size && _PyString_Resize(&buffer, sz) < 0)
        return NULL;

据我所知,这段代码运行良好,但我想知道_PyString_Resize. 如果 sz 小于 buffer_size,它是否使用它重新分配内存的现有缓冲区?

从效率的角度来看,我可能更喜欢前者来避免缓冲区内容的无用副本,即使它消耗的内存比必要的多。另一方面,重新分配内存也可能有助于减少内存占用。

那么 _PyString_Resize 是做什么的呢?有没有一种简单的方法来控制这种行为?

4

1 回答 1

3

是的,_PyString_Resize确实realloc- 毕竟,这是你要求它做的:-)

如果您想保存重新分配,也许您可read​​以进入堆栈上的缓冲区,然后从中创建字符串对象。类似的东西(未编译和测试,因此将其视为伪代码):

char cbuf[BUFFER_SIZE];
int sz = read(cbuf, BUFFER_SIZE);
PyObject * buffer = PyString_FromStringAndSize(cbuf, sz);

_PyString_Resize另外,请注意(它在)实现上面的警告Objects/stringobject.c

下面的函数打破了字符串不可变的概念:
它改变了字符串的大小。只有当只有一个模块引用该对象时,我们才能摆脱这一点。您也可以认为它创建了一个新的字符串对象并销毁旧的字符串对象,但效率更高。在任何情况下,如果代码的其他部分可能已经知道该字符串,请不要使用它...

于 2011-03-22T14:24:29.810 回答