Windows 中 posix_memalign 的正确替代品是啥?

Posted

技术标签:

【中文标题】Windows 中 posix_memalign 的正确替代品是啥?【英文标题】:Whats the correct replacement for posix_memalign in Windows?Windows 中 posix_memalign 的正确替代品是什么? 【发布时间】:2016-02-15 05:34:37 【问题描述】:

我目前正在尝试在 Windows 中构建 word2vec。但是posix_memalign() 函数存在问题。大家都建议用_aligned_malloc(),但是参数个数不一样。那么 Windows 中 posix_memalign() 的最佳等效项是什么?

【问题讨论】:

见:this question a = posix_memalign((void **)&syn1neg, 128, (long long)vocab_size * layer1_size * sizeof(real)); 例如如何更改为使用malloc? 有一个whole section in MSDN 专门用于 Windows 上的数据对齐。您如何阅读 Windows 函数的文档,然后阅读 POSIX 函数的文档,然后尝试了解什么参数代表什么? @HristoIliev 如果我编写自己的代码,我会这样做。我只需要建立别人的图书馆。如果我害怕构建它不正确(意外的粉碎或其他东西)。刚刚向已经面临同样问题的程序员提出了快速问题。 只需将#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno) 添加到您的Windows 版本。 :-) 【参考方案1】:

_aligned_malloc() 应该是posix_memalign() 的合适替代品,参数不同,因为posix_memalign() 返回错误而不是在失败时设置errno,其他它们是相同的:

void* ptr = NULL;
int error = posix_memalign(&ptr, 16, 1024);
if (error != 0) 
  // OMG: it failed!, error is either EINVAL or ENOMEM, errno is indeterminate

变成:

void* ptr = _aligned_malloc(1024, 16);
if (!ptr) 
  // OMG: it failed! error is stored in errno.

【讨论】:

errno 的值在调用posix_memalign(3) 后是indeterminate!与“未更新”不同。 注意posix_memalign返回的指针可以传给free,但是_aligned_malloc返回的指针必须传给_aligned_free【参考方案2】:

如果你比较possix_memalign声明:

int posix_memalign(void **memptr, size_t alignment, size_t size);

带有_aligned_malloc 声明:

void * _aligned_malloc(size_t size, size_t alignment);

您看到_aligned_malloc 缺少void **memptr 参数,但它返回void *

如果你的代码是这样的:

void * mem;
posix_memalign(&mem, x, y);

现在是(注意x, y 现在是y, x):

void * mem;
mem = _aligned_malloc(y, x);

【讨论】:

谢谢,我没发现它被置换了。 有细微的差别。 POSIX 函数要求对齐既是sizeof(void *) 的倍数又是2 的幂。 Windows CRT 函数将该要求放宽到只有 2 的幂(即不是指针大小的倍数)。这仅在从 Windows 移植到 POSIX 时相关,因为在相反的情况下始终满足要求。【参考方案3】:

谢谢大家。根据我喜欢的一些存储库中的代码和您的建议,我成功地构建了 EXE。这是我使用的代码:

#ifdef _WIN32
static int check_align(size_t align)

    for (size_t i = sizeof(void *); i != 0; i *= 2)
    if (align == i)
        return 0;
    return EINVAL;


int posix_memalign(void **ptr, size_t align, size_t size)

    if (check_align(align))
        return EINVAL;

    int saved_errno = errno;
    void *p = _aligned_malloc(size, align);
    if (p == NULL)
    
        errno = saved_errno;
        return ENOMEM;
    

    *ptr = p;
    return 0;

#endif

更新

看起来@alk 为这个问题提出了最佳解决方案:

#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno)

【讨论】:

更新中的行为我解决了问题【参考方案4】:

请注意,从 _aligned_malloc() 获得的内存必须使用 _aligned_free() 释放,而 posix_memalign() 仅使用常规 free()。所以你想添加类似的东西:

#ifdef _WIN32
#define posix_memalign_free _aligned_free
#else
#define posix_memalign_free free
#endif

【讨论】:

【参考方案5】:

从 C11 开始,C 标准库中有aligned_alloc

_aligned_malloc/_aligned_free相比,可以使用常规free释放内存,这是此功能的主要优点。

int *p2 = aligned_alloc(1024, 1024*sizeof *p2);
printf("1024-byte aligned addr: %p\n", (void*)p2);
free(p2);

但是,free 的易用性正是 Visual Studio 不太可能实现它的原因,请参阅std::aligned_alloc() missing from visual studio 2019?c++。

【讨论】:

以上是关于Windows 中 posix_memalign 的正确替代品是啥?的主要内容,如果未能解决你的问题,请参考以下文章

posix_memalign 有对应的 c++ 吗?

posix_memalign、malloc 和 calloc 与 lli 解释器有问题

C++ 中的 posix_memalign() 函数

我们啥时候需要使用 posix_memalign 而不是 malloc?

sigsegv 发生在 posix_memalign 在某些设备中释放后立即发生并在 AIX 中编译选项

如何使用 posix_memalign 动态分配 64B 对齐的 2D 指针数组