我正在编写一个 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);
当我使用 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
谁能解释一下为什么不正确第一个块在 Python3 下工作,但在 2.7 下不工作,更重要的是为什么correct第二个块在Python3下不起作用?
UPDATE 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);
Under Python 2.7:此代码按预期运行。
Under Python 3.1:此代码按预期运行。
Under Python 3.2:此代码生成mem_ret == ENOMEM
并返回 NULLbuffer
Under Python 3.3:此代码按预期运行。
Ubuntu 存储库中未包含的 Python 版本是从 PPA 安装的,地址为https://launchpad.net/~fkrull/+archive/deadsnakes https://launchpad.net/~fkrull/+archive/deadsnakes
如果标记为 Python 二进制文件的版本可信,那么我安装的版本是:
python2.7
python3.1
python3.2mu (--with-pymalloc --with-wide-unicode)
python3.3m (--with-pymalloc)
默认 Python3 发行版中使用 Wide-unicode 标志是否会导致此错误?如果是这样,这是怎么发生的?
为了清楚起见,ENOMEM
任何变体都会发生分配失败malloc()
,甚至像这样简单的事情malloc(512)
.