我正在用 C 语言开发一个项目,它需要 memalign()。确实,posix_memalign() 也可以,但是 darwin/OSX 缺少这两个。
有什么好的解决方案可以解决 memalign 的问题?如果我要撕掉 memalign.c 并将其放入我的项目中,我不了解 posix-C 代码的许可——我不想要任何病毒类型的许可 LGPL-ing 我的整个项目。
Mac OS X 似乎是16 字节内存对齐的。
引自网站:
我很难找到关于 MacOS X 内存对齐的明确声明,所以我做了自己的测试。在 10.4/intel 上,堆栈和堆内存都是 16 字节对齐的。所以移植软件的人可以停止寻找 memalign() 和 posix_memalign()。这不是必需的。
posix_memalign()
迟到了,但更新版本的 OSX确实有posix_memalign()
. 在与页面边界对齐时,您可能需要这样做。例如:
#include <stdlib.h>
char *buffer;
int pagesize;
pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize == -1) handle_error("sysconf");
if (posix_memalign((void **)&buffer, pagesize, 4 * pagesize) != 0) {
handle_error("posix_memalign");
}
需要注意的一点是,与 不同的是memalign()
,posix_memalign()
它**buffer
作为参数并返回一个整数错误代码。
自己做应该很容易,不是吗?类似于以下内容(未测试):
void *aligned_malloc( size_t size, int align )
{
void *mem = malloc( size + (align-1) + sizeof(void*) );
char *amem = ((char*)mem) + sizeof(void*);
amem += align - ((uintptr)amem & (align - 1));
((void**)amem)[-1] = mem;
return amem;
}
void aligned_free( void *mem )
{
free( ((void**)mem)[-1] );
}
(感谢乔纳森莱弗勒)
编辑: 关于扯掉另一个 memalign 实现,问题不在于许可。相反,您会遇到困难,即任何好的 memalign 实现都将成为堆管理器代码库的组成部分,而不是简单地分层在 malloc/free 之上。因此,将它移植到不同的堆管理器时会遇到严重的麻烦,尤其是当您无法访问它的内部时。
为什么您要移植的软件需要 memalign() 或 posix_memalign()?它是否将它用于比 austirg 引用的 16 字节对齐更大的对齐?
我看到 Mike F 发布了一些代码——它看起来比较简洁,尽管我认为 while 循环可能不是最佳的(如果所需的对齐是 1KB,它可能会迭代很多次)。
不:
amem += align - ((uintptr)amem & (align - 1));
一次手术就能到达那里?
从 macosx 手册页:
malloc()、calloc()、valloc()、realloc() 和 reallocf() 函数分配内存。分配的内存对齐,以便它可以用于任何数据类型,包括 AltiVec 和 SSE 相关类型。free() 函数释放通过前面的分配函数创建的分配。
是的,Mac OS X在ABI中确实有 16 字节内存对齐。您不需要使用 memalign()。如果您的内存要求是 16 倍,那么我不会实现它,也许只是添加一个断言。
如果您需要一个任意对齐的 malloc,请查看 x264 的 malloc(git 存储库中的 common/common.c),它为没有 malloc.h 的系统提供了自定义 memalign。它的代码极其微不足道,以至于我什至不认为它具有版权,但是您在看到它之后应该可以轻松地实现自己的代码。
当然,如果你只需要 16 字节对齐,如上所述,它在 OS X ABI 中。
可能值得建议在您的代码中使用 Doug Lea 的 malloc。链接文本
感谢您的帮助,伙计们......在我的情况下有所帮助(OpenCascade src/Image/Image_PixMap.cxx,OSX10.5.8 PPC)
结合上面的答案,如果不是特别熟悉 malloc 等,这可能会节省一些人的挖掘或灌输希望:
我正在构建的相当大的项目只有一个对 posix_memalign 的引用,事实证明这是一堆不包括 OSX 但确实包括 BORLANDC 的预处理器条件的结果,这证实了其他人认为它是安全的在某些情况下使用 malloc:
#if defined(_MSC_VER)
return (TypePtr )_aligned_malloc (theBytesCount, theAlign);
#elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
return (TypePtr ) _mm_malloc (theBytesCount, theAlign);
#elif defined(__BORLANDC__)
return (TypePtr ) malloc (theBytesCount);
#else
void* aPtr;
if (posix_memalign (&aPtr, theAlign, theBytesCount))
{
aPtr = NULL;
}
return (TypePtr )aPtr;
#endif
因此,正如其他人所建议的那样,它可以像使用 malloc 一样简单。
例如这里:在__BORLANDC__
上面移动条件__GNUC__
并添加APPLE:
#elif (defined(__BORLANDC__) || defined(__APPLE__)) //now above `__GNUC__`
注意:我没有像上面所说的 OS X 那样检查 BORLANDC 是否使用 16 字节对齐。我也没有验证 PPC OS X 确实如此。然而,这种用法表明这种对齐并不是特别重要。(希望它有效,并且对您的搜索者来说也很容易!)