我正在用C编写一个项目,它需要memalign()。实际上,posix_mealign()也可以,但darwin/OSX两者都不具备。
什么是memalign中shoehorn的好解决方案?如果我要剽窃memalign.C并将其放在我的项目中,我不理解posix-C代码的许可——我不希望在我的整个项目中使用任何病毒型许可LGPL。
Mac OS X似乎是16字节内存对齐的。
网站报价:
我很难找到一个确定的关于MacOS X内存对齐的声明所以我自己做了测试。在10.4/intel上,堆栈和堆内存都是16字节对齐。所以人们移植软件可以停止查找memalign(),并且posix_memalign()。不需要它。
更新:OSX现在有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] );
}
(感谢Jonathan Leffler)
编辑:关于剥离另一个memalign实现,问题不在于许可。相反,您会遇到这样的困难,即任何好的memalign实现都将是堆管理器代码库的一个组成部分,而不是简单地分层在malloc/free之上。因此,将它移植到不同的堆管理器时会遇到严重的问题,尤其是当您无法访问它的内部时。
为什么要移植的软件需要memalign()或posix_meagn()?它是否将其用于大于austirg引用的16字节对齐的对齐?
我看到Mike F发布了一些代码——它看起来相对整洁,尽管我认为while循环可能是次优的(如果需要的对齐是1KB,它可以迭代很多次)。
没有:
amem += align - ((uintptr)amem & (align - 1));
一次手术就能到达那里?
是的,Mac OS X在ABI中确实有16字节内存对齐。您不需要使用memalign()。如果内存需求是16,那么我不会实现它,也许只是添加一个断言。
从macosx手册页:
malloc()、calloc()、valloc(,realloc()和reallocf()函数分配内存。分配的内存是对齐的,这样它就可以用于任何数据类型,包括AltiVec和SSE相关类型。免费()函数释放通过前面的分配创建的分配功能。
如果您需要一个任意对齐的malloc,请查看x264的malloc(git存储库中的common/common.c),它为没有malloc.h的系统提供了一个自定义的memalign。它的代码非常琐碎,我甚至不认为它是可版权使用的,但您应该可以在看到它后轻松地实现自己的代码。
当然,如果您只需要16字节对齐,如上所述,它在OSXABI中。
建议在代码中使用Doug Lea的malloc可能是值得的。链接文本
谢谢大家的帮助。。。在我的案例中有所帮助(OpenCascade src/Image/Image_PixMap.cxx,OSX10.5.8 PPC)
结合上面的答案,如果不是特别熟悉malloc等,这可能会为人们省去一些挖掘或灌输希望
我正在构建的这个相当大的项目只有一个对posix_meagn的引用,事实证明这是一系列预处理器条件的结果,这些条件不包括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__`
注意:我检查了BORLANDC是否像上面提到的OS X一样使用16字节对齐。我也没有验证PPC OS X是这样做的。然而,这种用法表明这种对齐并不特别重要。(希望它能起作用,对搜索者来说也能这么容易!)