C++ 运行时检查失败#4-此函数保留的#alloca内存周围的堆栈区域已损坏?
我使用Visual C++ 2019,STDC++ + 14和STDC++ + 17都产生相同的错误。C++ 运行时检查失败#4-此函数保留的#alloca内存周围的堆栈区域已损坏?,c++,stack,runtime-error,alloca,C++,Stack,Runtime Error,Alloca,我使用Visual C++ 2019,STDC++ + 14和STDC++ + 17都产生相同的错误。 这段代码有什么问题?我假设这只是一段示例代码,因为如果您只是想打印数字0..n,那么您完全没有理由使用数组:-) 至于您的实际问题,alloca函数,如malloc,分配了大量字节。如果将其视为有许多int值(几乎可以肯定大于一个字节),则不会有好的结果。这在对话框中得到了确认,其中大小为10,但每个数组元素占用4个: Run-Time Check Failure #4 - Stack ar
这段代码有什么问题?我假设这只是一段示例代码,因为如果您只是想打印数字
0..n
,那么您完全没有理由使用数组:-)
至于您的实际问题,
alloca
函数,如malloc
,分配了大量字节。如果将其视为有许多int
值(几乎可以肯定大于一个字节),则不会有好的结果。这在对话框中得到了确认,其中大小为10,但每个数组元素占用4个:
Run-Time Check Failure #4 - Stack area around _alloca memory reserved by this function is corrupted
在任何情况下,我都会避免alloca,因为:
new
那样引发异常,那么它就会有一个令人讨厌的坏习惯Size: 10
Data: <> 00 00 00 00 01 00 00 00 02 00
\_________/ \_________/ \____
arr[0] arr[1] ar
int *arr = (int*) alloca(n * sizeof(*arr)); // n ints, not bytes.
另外,你会注意到我也改为使用size\u t
而不是int
作为大小和索引-我认为这更适合。当然,这是使用堆而不是堆栈,但根据前面关于alloca
的评论,这是更安全的方法
如果您保证对尺寸进行一定限制,例如:
#include <iostream>
#include <memory>
void print_vals(size_t n) {
std::unique_ptr<int[]> arr(new int[n]);
for (size_t i = 0; i < n; i++)
arr[i] = static_cast<int>(i);
for (size_t i = 0; i < n; i++)
std::cout << arr[i] << ' ';
std::cout << '\n';
}
int main() {
print_vals(5);
print_vals(10);
}
但这实际上并不能保证它的安全性,如果你打算这样做,你也可以使用固定的缓冲区,因为你知道最大大小:
void print_vals(size_t n) {
if (n >= 100) {
doSomethingIntelligent();
return;
}
int *arr = (int *)alloca(n * sizeof(*arr));
...
}
我想提出的另一个解决方案是:如果您的目的是尽可能提高效率,那么您可以使用混合方法。我的意思是,在低于一定大小时使用本地缓冲区,并仅在需要时分配内存:
void print_vals(size_t n) {
int arr[100];
if (n >= sizeof(arr) / sizeof(*arr)) {
doSomethingIntelligent();
return;
}
...
}
void打印值(大小){
//默认使用本地缓冲区。
int localBuff[100];
int*arr=localBuff;
//如果需要更多空间,请分配自动释放智能指针。
std::唯一的\u ptr allocBuff;
如果(n>=sizeof(localBuff)/sizeof(*localBuff)){
allocBuff.reset(新整数[n]);
arr=allocBuff.get();
}
//这里,arr指向一个足够大的缓冲区。
...
函数的参数是要分配的字节,因此元素的大小必须乘以元素的数量
可以这样做:
void print_vals(size_t n) {
// Default to using local buffer.
int localBuff[100];
int *arr = localBuff;
// If more space needed, allocate an auto-freeing smart pointer.
std::unique_ptr<int[]> allocBuff;
if (n >= sizeof(localBuff) / sizeof(*localBuff)) {
allocBuff.reset(new int[n]);
arr = allocBuff.get();
}
// Here, arr points to to a big-enough buffer.
...
你为什么在C++中使用原始的C风格记忆管理?有什么理由吗?这个代码大声地发出一个简单的<代码> STD::VECor < /C>ῥεῖ 因为Visual C++不允许VLA。这回答了你的问题吗?@ StasExchange 123 HMM,好。这似乎是有意义的。否则你需要实现你自己的描述:谢谢。我不知道我是怎么错过的……但是为什么它打印正确的值tho?@ StasExchange 123,你做的是未定义的行为。这意味着UND。定义为“它甚至可以工作,至少在一段时间内”:-)可能发生的情况是,它在分配的空间之外自由地写入和读取内存,但是,当要退出函数时,发生了损坏。实际上,你很幸运它捕获了它,而不是使用堆栈上可能损坏的返回值返回到
main
。我们不得不使用EcTimes的东西,像它几乎肯定大于一个字节,我们不能只是让所有的512位,并用它做?@ PaxDabLo我使用它,因为VLAS是不允许在VisualC++中。还有其他的方式吗?@ StAcExchange 123:我已经添加了一些其他选项供您考虑。
void print_vals(size_t n) {
int arr[100];
if (n >= sizeof(arr) / sizeof(*arr)) {
doSomethingIntelligent();
return;
}
...
}
void print_vals(size_t n) {
// Default to using local buffer.
int localBuff[100];
int *arr = localBuff;
// If more space needed, allocate an auto-freeing smart pointer.
std::unique_ptr<int[]> allocBuff;
if (n >= sizeof(localBuff) / sizeof(*localBuff)) {
allocBuff.reset(new int[n]);
arr = allocBuff.get();
}
// Here, arr points to to a big-enough buffer.
...
int *arr = (int *)alloca(sizeof(*arr) * n);