bra*_*ier 9 c python memory-management cpython
我正在编写一个Python模块来在O_DIRECT上下文中执行IO.O_DIRECT的一个限制是你必须读入对应于2.4和2.5内核的4096字节边界的缓冲区,2.6及以上将接受512的任意倍数.
对此明显的内存分配候选是 posix_memalign(void **memptr, size_t alignment, size_t size)
在我的代码中,我分配了一个像这样的区域:
char *buffer = NULL;
int mem_ret = posix_memalign((void**)&buffer, alignment, size);
if (!buffer) {
PyErr_NoMemory();
return NULL;
}
/* I do some stuff here */
free(buffer);
Run Code Online (Sandbox Code Playgroud)
当我用python3.2编译和导入模块时,这个(以及未示出的模块的其余部分)工作正常.
当我尝试使用python2.7(我想保持兼容性)时,它会抛出PyErr_NoMemory异常,并mem_ret == ENOMEM指示它无法分配.
为什么我编译的Python版本会影响posix_memalign的运行方式?
操作系统:Ubuntu 12.04 LTS
编译器:Clang + GCC显示相同的行为
UPDATE
我现在有了一段代码,感谢user694733
但是它的工作原理使我更加困惑:
#if PY_MAJOR_VERSION >= 3
char *buffer = NULL;
int mem_ret = posix_memalign((void**)&buffer, alignment, count);
#else
void *mem = NULL;
int mem_ret = posix_memalign(&mem, alignment, count);
char *buffer = (char*)mem;
#endif
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释为什么不正确的第一个块在Python3下运行,而不是2.7,更重要的是为什么正确的第二个块在Python3下不起作用?
更新2
情节变得浓密,已经确定了下面代码的正确形式,我测试了4个不同版本的Python.
void *mem = NULL;
int mem_ret = posix_memalign(&mem, alignment, count);
char *buffer = (char*)mem;
if (!buffer) {
PyErr_NoMemory();
return NULL;
}
/* Do stuff with buffer */
free(buffer);
Run Code Online (Sandbox Code Playgroud)
在Python 2.7下:此代码按预期运行.
在Python 3.1下:此代码按预期运行.
在Python 3.2下:此代码mem_ret == ENOMEM为buffer
Under Python 3.3生成并返回NULL :此代码按预期运行.
未包含在Ubuntu存储库中的Python版本是从PPA安装的,位于https://launchpad.net/~fkrull/+archive/deadsnakes
如果要相信版本标记的Python二进制文件,我安装的版本是:
python2.7
python3.1
python3.2mu (--with-pymalloc --with-wide-unicode)
python3.3m (--with-pymalloc)
Run Code Online (Sandbox Code Playgroud)
在默认的Python3发行版中使用wide-unicode标志会导致此错误吗?如果是这样,这是怎么回事?
为清楚起见,ENOMEM分配失败将发生在任何变体中malloc(),即使是简单的变体malloc(512).