使用alloca时出现访问冲突错误

6

我的stackAlloc函数长这样:

void* stackAlloc(size_t size) {
    if (size > maxStackAllocation)
        return malloc(size);
    else 
        return _alloca(size);
}
void stackAllocFree(void *ptr, size_t size) {
    if (size > maxStackAllocation) {
        free(ptr);
    }
}

如果我更改stackAlloc函数,始终使用malloc而不是alloca,那么一切都可以正常工作。
我将该函数更改为一个宏,现在它按预期工作:
#define maxStackAllocation 1024
#define stackAlloc(size) \
( \
    (size > maxStackAllocation)? \
         malloc(size): \
        _alloca(size) \
)

#define stackAllocFree(ptr, size) \
( \
    (size > maxStackAllocation)? \
        free(ptr): \
    void() \
)

maxStackAllocation的值是多少?我建议您也阅读有关alloca文档页面上的所有警告。 - Jonathon Reinhart
这里只分配了124个字节,它是1024。 - hidayat
由于Vulkan显然是一个C API,为什么不使用可变长度数组呢? - Cody Gray
我正在使用VS2015,它不支持它。 - hidayat
2
@dev 你在说什么?他的代码按照你描述的方式工作。如果stackAlloc调用了malloc,那么stackAllocFree就会调用free。没有理由释放使用_alloca释放的内存。 - Cody Gray
你的代码看起来没问题。请展示一个 MCVE。向我们展示你如何调用 stackAlloc... 函数。问题不在你在问题中展示的代码中。 - Jabberwocky
3个回答

9
假设你正在 Windows 上运行,因为你的代码调用了 _alloca() 函数,根据 MSDN 文档:

_alloca 函数从程序堆栈中分配 size 字节。当调用函数退出时,分配的空间会自动释放。

请注意,内存在调用函数退出时被释放,我假设这也意味着调用函数返回。
您的代码:
void* stackAlloc(size_t size) {
    if (size > maxStackAllocation)
        return malloc(size);
    else 
        return _alloca(size);
}

返回值,从而释放通过_alloca()获取的内存。


1
我想知道如果该函数被标记为 static inline __forceinline,是否也适用。 - Jonathon Reinhart
2
@JonathonReinhart,当然它也适用于那里。alloca不是一个“真正的”malloc,它只是从堆栈指针中减去更多的空间。这意味着它将始终自动释放,因为CPU会处理它。因此,函数是否内联并不重要。 - Devolus
1
@JonathonReinhart 内联不允许更改内联函数的语义。(内联不是类似宏替换的操作。) - molbdnilo
1
@Devolus 我理解 alloca 的实现方式。如果在(内联)函数中减去了 esp,那么编译器会在内联函数结束时立即将其添加到 esp 中吗?还是会等到调用函数返回时再进行清理? - Jonathon Reinhart
@molbdnilo 对于“正常”的内联,我同意。但是__forceinline是非标准的,所以在这种情况下让类似于alloca的东西“工作”是合理的。无论哪种方式,在这里的“正确”答案是将此stackAlloc设置为宏,或者根本不使用alloca - Jonathon Reinhart
显示剩余2条评论

3

从手册页面上可以看到,

当调用 alloca() 函数的函数返回给其调用者时,这个临时空间将自动释放。

因此,无论何时您的 stackAlloc 函数返回,它都会自动释放内存。


0

这个可以运行,但我不建议在生产环境中使用:

#include <iostream>
#include <alloca.h>

auto stackAlloc(const size_t size)
{
    return [size](){ return alloca(size); };
}

int main() {
    char *ch = (char *)stackAlloc(40000)();
    ch[39999] = '\0';

    return 0;
}

反向检查:如果我减少stackAlloc的参数,它不起作用(这是预期的行为)。 可以在stackAlloc中添加检查等内容(通过返回不同的lambda或让lambda执行检查)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接