将数组传递给 C++ 中的函数时如何避免堆栈溢出?
How to avoid stack overflow when passing an array to a function in C++?
我正在编写一个代码,其中通过将指针传递到第一个位置来将数组传递给函数。在函数中,使用了数组的一部分。这会造成不安全的情况,因为如果调用函数没有正确猜测数组的最大大小,则被调用函数可能会写入超出数组大小的值,并可能发生堆栈溢出。我正在考虑对此的解决方案,并考虑使用函数模板并将数组作为参考传递,如本例所示。
modifyArray.h
#define MAXSIZE 10
class modifyArray
{
public:
void create();
void unsafeFunction(double*);
template<int N>
void safeFunction(double (&array)[N] );
private:
int computeLength();
};
modifyArray.cpp
#include <iostream>
#include "modifyArray.h"
int modifyArray::computeLength()
{
return 11;
}
void modifyArray::create()
{
double testarray[MAXSIZE];
unsafeFunction(testarray);
safeFunction(testarray);
}
void modifyArray::unsafeFunction(double* array)
{
int operatingSize = computeLength();
for(int i = 0; i < operatingSize; i++) {
array[i] = i*i;
}
}
template<int N>
void modifyArray::safeFunction(double (&array)[N] )
{
int operatingSize = computeLength();
std::cout<< "Max size" << N <<std::endl;
if(operatingSize > N) return; // Return or raise an exception
for(int i = 0; i < operatingSize; i++) {
array[i] = i*i;
}
}
main.cpp
#include "modifyArray.h"
int main(int argc, const char * argv[]) {
modifyArray C;
C.create();
return 0;
}
我正在寻找一种对现有代码侵入性最小的解决方案。在这里我只需要添加一个模板语句,将参数从 double* 更改为引用,并插入一个 if 语句来检查大小。我不想进行重大重写。此外,我不想使用动态分配、向量或 std::array,主要是出于性能原因。这是数值模拟代码中的低级函数,性能非常重要。有更好的解决方案吗?做我正在做的事情有陷阱吗?
如果您真的想使用原始数组,并且想安全地修改数组的所有元素而不用遍历末尾,那么您可以通过引用传递数组,然后使用 range based for loop。
tmeplate <typename T, typename Function, std::size_t N>
void do_work(T (&arr)[N], Function f)
{
for (auto & e : arr)
e = f();
}
以上将调用函数的结果应用于数组的每个元素,并保证留在数组的边界内。你可以这样使用它
int main()
{
int arr[10];
do_work(arr, []() { static int i = 0; i++; return i * i; });
for (auto e : arr)
std::cout << e << " ";
}
输出:
1 4 9 16 25 36 49 64 81 100
我正在编写一个代码,其中通过将指针传递到第一个位置来将数组传递给函数。在函数中,使用了数组的一部分。这会造成不安全的情况,因为如果调用函数没有正确猜测数组的最大大小,则被调用函数可能会写入超出数组大小的值,并可能发生堆栈溢出。我正在考虑对此的解决方案,并考虑使用函数模板并将数组作为参考传递,如本例所示。
modifyArray.h
#define MAXSIZE 10
class modifyArray
{
public:
void create();
void unsafeFunction(double*);
template<int N>
void safeFunction(double (&array)[N] );
private:
int computeLength();
};
modifyArray.cpp
#include <iostream>
#include "modifyArray.h"
int modifyArray::computeLength()
{
return 11;
}
void modifyArray::create()
{
double testarray[MAXSIZE];
unsafeFunction(testarray);
safeFunction(testarray);
}
void modifyArray::unsafeFunction(double* array)
{
int operatingSize = computeLength();
for(int i = 0; i < operatingSize; i++) {
array[i] = i*i;
}
}
template<int N>
void modifyArray::safeFunction(double (&array)[N] )
{
int operatingSize = computeLength();
std::cout<< "Max size" << N <<std::endl;
if(operatingSize > N) return; // Return or raise an exception
for(int i = 0; i < operatingSize; i++) {
array[i] = i*i;
}
}
main.cpp
#include "modifyArray.h"
int main(int argc, const char * argv[]) {
modifyArray C;
C.create();
return 0;
}
我正在寻找一种对现有代码侵入性最小的解决方案。在这里我只需要添加一个模板语句,将参数从 double* 更改为引用,并插入一个 if 语句来检查大小。我不想进行重大重写。此外,我不想使用动态分配、向量或 std::array,主要是出于性能原因。这是数值模拟代码中的低级函数,性能非常重要。有更好的解决方案吗?做我正在做的事情有陷阱吗?
如果您真的想使用原始数组,并且想安全地修改数组的所有元素而不用遍历末尾,那么您可以通过引用传递数组,然后使用 range based for loop。
tmeplate <typename T, typename Function, std::size_t N>
void do_work(T (&arr)[N], Function f)
{
for (auto & e : arr)
e = f();
}
以上将调用函数的结果应用于数组的每个元素,并保证留在数组的边界内。你可以这样使用它
int main()
{
int arr[10];
do_work(arr, []() { static int i = 0; i++; return i * i; });
for (auto e : arr)
std::cout << e << " ";
}
输出:
1 4 9 16 25 36 49 64 81 100