Python C模块 - Malloc在特定版本的Python中失败

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 == ENOMEMbuffer
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).

Dim*_*nek 1

为了快速解决问题,请坚持mmap而不是malloc+memalign