0

I am working on a code where an array is passed to a function by passing the pointer to the first location. In the function, part of the array is used. This creates an unsafe situation because there is a chance if the caller function does not guess the max size of the array correctly the callee function can write past the array size and a stack overflow can occur. I was thinking of a solution to this and thought of using a function template and passing the array as reference as shown in this example.

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;
}

I am looking for a solution that is minimally invasive to the existing code. Here I just have to add a template statement, change the argument from double* to reference, and insert an if statement to check the size. I don’t want to do a major rewrite. Also I don’t want to use dynamic allocation, vector, or std::array mostly because of the performance reasons. This is a low level function in a numerical simulation code and performance is very important. Is there a better solution? Is there a pitfall to doing what I am doing?

6
  • 4
    [...]or std::array mostly because of the performance reasons. A std::array it just a wrapper for an array and has the same run-time performance as a raw array. Commented Apr 26, 2016 at 14:28
  • 2
    Either pass another parameter stating the number of elements or just use a std::array. The performance will be the same. Commented Apr 26, 2016 at 14:30
  • 1
    Also I don't think you are describing a stack overflow. You are describing an out-of-bounds exception. Commented Apr 26, 2016 at 14:32
  • std::array mostly because of the performance reasons. -- The std::array alleviates all of the issues you stated in your post. A std::array knows its own size, so you don't need to pass another parameter denoting this information, and as others stated, a std::array is an array, just with member functions. So there is no degradation in performance. Commented Apr 26, 2016 at 14:51
  • Prefer to pass std::vector. They are a lot easier than arrays. With arrays, you will need to pass the array, the capacity and optionally the number of occupied elements. The capacity of an array is lost when it is passed to a function. Commented Apr 26, 2016 at 14:55

1 Answer 1

4

If you really want to work with raw arrays and you want to safely modify all of the elements of the array without walking of the end then you can pass the array by reference and then use a 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();
}

The above will apply the result of calling function to every element of the array and is guaranteed to stay in the bounds of the array. You could use it like

int main()
{
    int arr[10];
    do_work(arr, []() { static int i = 0; i++; return i * i; });
    for (auto e : arr)
        std::cout << e << " ";
}

output:

1 4 9 16 25 36 49 64 81 100 

Live Example

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the idea. In your example, the loop in do_work always goes over the complete length of the arr, in my actual code, I want to call do_work multiple times on the same array but utilize different lengths of the array each time. But thanks for the idea. Also safeFunction and unsafeFunction and computeLength here are just examples, my actual code does more complicated things.
@user3469604 If the us the case then you can always compare how far you want to run against N as N will be the size of the array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.