0

Ich arbeite an einem Code, bei dem ein Array an eine Funktion übergeben wird, indem der Zeiger an den ersten Ort übergeben wird. In der Funktion wird ein Teil des Arrays verwendet. Dies führt zu einer unsicheren Situation, da die Chance besteht, dass die Aufruferfunktion die maximale Größe des Arrays nicht richtig erraten kann, da die aufgerufene Funktion die Array-Größe überschreiben kann und ein Stack-Überlauf auftreten kann. Ich dachte über eine Lösung nach und dachte darüber nach, eine Funktionsvorlage zu verwenden und das Array als Referenz zu übergeben, wie in diesem Beispiel gezeigt.Wie vermeidet man Stapelüberlauf beim Übergeben eines Arrays an eine Funktion 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; 
} 

Ich suche eine Lösung, die für den bestehenden Code minimal invasiv ist. Hier muss ich nur eine Template-Anweisung hinzufügen, das Argument von double * in referenz ändern und eine if-Anweisung einfügen, um die Größe zu überprüfen. Ich möchte keine größere Überarbeitung machen. Auch möchte ich nicht wegen der Leistungsgründe dynamische Zuordnung, Vektor oder std :: array verwenden. Dies ist eine Low-Level-Funktion in einem numerischen Simulationscode und die Leistung ist sehr wichtig. Gibt es eine bessere Lösung? Gibt es eine Falle, was ich tue?

+4

* [...] oder std :: Array vor allem wegen der Performance-Gründen *. Ein 'std :: array' ist nur ein Wrapper für ein Array und hat dieselbe Laufzeitperformance wie ein Raw-Array. – NathanOliver

+2

Übergeben Sie entweder einen anderen Parameter mit der Anzahl der Elemente oder verwenden Sie einfach ein 'std :: array'. Die Leistung wird gleich sein. –

+1

Auch ich glaube nicht, dass Sie einen Stapelüberlauf beschreiben. Sie beschreiben eine Out-of-Bounds-Ausnahme. –

Antwort

4

Wenn Sie wirklich mit Raw-Arrays arbeiten möchten und alle Elemente des Arrays sicher ändern möchten, ohne am Ende zu gehen, können Sie das Array als Referenz übergeben und dann range based for loop verwenden.

tmeplate <typename T, typename Function, std::size_t N> 
void do_work(T (&arr)[N], Function f) 
{ 
    for (auto & e : arr) 
     e = f(); 
} 

Das oben wird das Ergebnis der Aufruf-Funktion auf jedes Element des Arrays anzuwenden und wird in den Grenzen des Arrays bleiben gewährleistet. Man könnte es wie

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

Ausgang verwenden:

1 4 9 16 25 36 49 64 81 100 

Live Example

+0

Vielen Dank für die Idee. In Ihrem Beispiel geht die Schleife in 'do_work' immer über die gesamte Länge des' arr', in meinem tatsächlichen Code möchte ich 'do_work' mehrere Male auf dem gleichen Array aufrufen, aber jedes Mal unterschiedliche Längen des Arrays verwenden.Aber danke für die Idee. Auch 'safeFunction' und' unsafeFunction' und 'computeLength' sind hier nur Beispiele, mein eigentlicher Code macht kompliziertere Dinge. – user3469604

+0

@ user3469604 Wenn das der Fall ist, dann können Sie immer vergleichen, wie weit Sie gegen 'N' laufen wollen, da' N' die Größe des Arrays ist. – NathanOliver