2017-02-08 3 views
0

Ich habe viele Beiträge mit dem gleichen Fehler gelesen, leider beschäftigen sich alle diese mit der Indizierung am Ende eines Arrays. In meinem Fall bekomme ich den Fehler, wenn ich das Array einer Variablen in meinem Konstruktor zuweisen.C++ Fehler bei der Verwendung von Array als Parameter

Hier ist mein Code:

Heap.cpp

#include "./Heap.h" 
#include <iostream> 
#include <sstream> 
// Provides floor, ceil, etc. 
#include <cmath> 

using namespace std; 

Heap::Heap() { 
    arraySize = 0; 
    n = 0; 
    A = NULL; 
} 

// This assumes that every element of the array is an 
// element of the heap. 
Heap::Heap(int* inArray, int inArraySize, int inHeapSize) { 
    // TODO: initialize your class data members. An array dynamically allocated 
    // as follows: 
    // A = new int[size]; 
    // If you allocate an array like this you MUST deallocate it in your 
    // destructor. This is done for you in the destructor below. 

    arraySize = inArraySize; 
    n = inHeapSize; 
    A = new int[arraySize]; 
    A = inArray; 
} 

// Destructor. Cleans up memory. 
Heap::~Heap() { 
    delete [] A; 
} 

// Note: the function name is prefixed by Heap:: (the class 
// name followed by two colons). Any function defined in 
// the .cpp file must have this prefix. 
int Heap::at(int i) const { 
    return A[i]; 
} 

int Heap::parent(int i) const{ 
    return (int) (i - 1)/2; 
} 

int Heap::left(int i) const { 
    return (i + 1)* 2 - 1; 
} 

int Heap::right(int i) const { 
    return (i + 1) * 2; 
} 

bool Heap::hasLeft(int i) const { 
    int leftIndex = left(i); 
    std::cout << "left index = " << leftIndex<< std::endl; 
    return false; 
} 

bool Heap::hasRight(int i) const{ 
    return false; 
} 

void Heap::maxHeapify(int i){ 

} 
// 
void Heap::buildMaxHeap(){ 

} 



bool Heap::operator==(const Heap& rhs) { 
    if (n != rhs.n) return false; 
    for (int i = 0; i < n; ++i) { 
    if (A[i] != rhs.A[i]) return false; 
    } 
    return true; 
} 

bool Heap::operator==(const int* rhs) { 
    for (int i = 0; i < n; ++i) { 
    if (A[i] != rhs[i]) return false; 
    } 
    return true; 
} 

std::ostream& operator<<(std::ostream& out, const Heap& h) { 
    out << "["; 
    for (int i = 0; i < h.n; ++i) { 
    out << h.A[i]; 
    if (i < h.n-1) { 
     out << ", "; 
    } 
    } 
    out << "]"; 
    return out; 
} 

string toDotImpl(const Heap& h, int i) { 
    using namespace std; 
    stringstream ss; 
    if (h.hasLeft(i)) { 
    ss << toDotImpl(h, h.left(i)); 
    ss << "\"" << h.at(i) << "\" -> \"" 
     << h.at(h.left(i)) << "\"\n"; 
    } 
    if (h.hasRight(i)) { 
    ss << toDotImpl(h, h.right(i)); 
    ss << "\"" << h.at(i) << "\" -> \"" 
     << h.at(h.right(i)) << "\"\n"; 
    } 
    return ss.str(); 
} 

string toDot(const Heap& h) { 
    using namespace std; 
    stringstream ss; 
    ss << "digraph G {\n"; 
    ss << "graph [ordering=\"out\"]\n"; 
    ss << "\"" << h.at(0) << "\"\n"; 
    ss << toDotImpl(h, 0); 
    ss << "}\n"; 
    return ss.str(); 
} 

und

Heap.h

#pragma once 

// Provides I/O 
#include <iostream> 
// Provides size_t 
#include <cstdlib> 
// Provides INT_MAX and INT_MIN 
// You can consider INT_MIN to be negative infinity 
// and INT_MAX to be infinity 
#include <climits> 

//------------------------------------------------------------ 
// Heap class 
//------------------------------------------------------------ 
class Heap { 
public: 
    // Constructor 
    Heap(); 

    // This constructor assumes that every element of the array is an 
    // element of the heap. 
    Heap(int* inArray, int inArraySize, int inHeapSize); 

    // Destructor 
    ~Heap(); 

    // Accesses an element of the array. 
    int at(int i) const; 

    // Gets parent index of element at i 
    int parent(int i) const; 

    // Return element to the left of i 
    int left(int i) const; 

    // Return element to the right of i 
    int right(int i) const; 

    // Checks if an element has a left child 
    bool hasLeft(int i) const; 

    // Checks if an elemnt has a right child 
    bool hasRight(int i) const; 

    // "Max heapifies" an array 
    void maxHeapify(int i); 

    // builds a max heap 
    void buildMaxHeap(); 


    // Allows comparison between results 
    bool operator==(const Heap& rhs); 
    bool operator==(const int* rhs); 

    // Useful for debugging. To use: 
    // Heap h; 
    // cout << h << endl; 
    friend std::ostream& operator<<(std::ostream& out, const Heap& h); 

private: 
    // The array 
    int* A; 

    // Size of the array 
    int arraySize; 

    // The number of elements in the heap 
    int n; 
}; 

// Useful for debugging. To use: 
// Heap h; 
// cout << h << endl; 
std::string toDot(const Heap& h); 

Der Code mit I genannt wird, kann die gesamte main.cpp enthalten, wenn nötig, aber es hat mehrere hundert Zeilen von Testfällen auskommentiert. int A[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; Heap h(A, 8, 8);

wenn ich A = inArray; kommentieren Sie das Programm läuft, so bin ich ziemlich sicher, das ist, wo das Problem ist.

A ist definiert in Heap.h als `int * A; Hier

ist der vollständige Fehler:

*** Error in `./project': free(): invalid size: 0x00007ffd84786660 *** Aborted (core dumped)

dies ist wahrscheinlich eine ganz einfache Frage, aber ich kann nicht herausfinden, was ist der Grund dafür, da ich glaube, dass dies eine Reihe von Größe inArraySize vom Typ int zuweisen sollte und dann ordnen Sie das gegebene Array inArray zu A.

Volle Offenlegung: Dies ist Teil einer Aufgabe, so zögern Sie nicht, zeigen Sie mir in die richtige Richtung, aber mein Professor ist in Ordnung mit uns stackoverflow verwenden, solange wir es platzieren .

+0

... und was ist der Fehler? (und welche Zeile ist es, etc.) – qxz

+3

Sie ordnen Speicher zu und dann auf der nächsten Zeile werfen Sie sofort die Adresse dieses Speichers weg, indem Sie 'A' neu zuweisen. Wollen Sie das wirklich tun? –

+1

Mögliches Duplikat von [Der sauberste Weg, um ein Array konstanter Größe in C++ 11 zu kopieren] (http://stackoverflow.com/questions/12328301/cleanest-way-to-copy-a-constant-size-array-in- c11) –

Antwort

2

Sie versuchen, ein Array zu kopieren, aber die Zuordnung Zeiger wie das ist nicht, wie es zu tun. Es gibt verschiedene Möglichkeiten.

Standard C++:

#include <algorithm> 

std::copy(inArray, inArray + inArraySize, A); 

Unter Verwendung von Standard-Container:

#include <vector> 

std::vector<int> A(inArray, inArray + inArraySize); 

alten Art C Art und Weise

memcpy(A, inArray, sizeof(int) * inArraySize); 
+0

Dies tat den Trick, Entschuldigung für die doppelte Frage, ich bin neu in C++ und dachte, nur die Zuweisung des Wertes würde es kopieren, aber nach dem Lesen der Antworten in den Duplikat Link sehe ich, warum es nicht – kalenpw

1

tun:

A = new int[arraySize]; 
A = inArray; 

Ist wie tun:

i = 5; 
i = 6; 

Die zweite Zuordnung überschreibt die erste.


daher als Ergebnis wird die Elementvariable A zeigt auf den gleichen Speicherblock durch das Eingabeargument wies inArray. Wenn Sie diesen Speicherblock nicht dynamisch zugewiesen haben (mit new), können Sie ihn nicht dynamisch freigeben (mit delete).

+0

Danke für den Hinweis, dass ich gerade das A überschrieb, das habe ich vorher nicht bemerkt. Entschuldigung für die Bearbeitung des Codes in meiner Frage, Ihre Antwort war hilfreich. – kalenpw

+0

@kalenpw: Gern geschehen :) –

1

Die Linien

A = new int[arraySize]; 
A = inArray; 

sind Ursache für zwei Probleme.

  1. Es ist ein Speicherleck. Der von new int[arraySize] zurückgegebene Wert ist verloren und kann nicht freigegeben werden.

  2. Wenn Sie im Destruktor delete [] A aufrufen, wäre das der Grund für das zweite Problem.

    • Wenn inArray dynamisch zugewiesen wurde und in der aufrufenden Funktion freigegeben, werden Sie zweimal delete auf demselben Zeiger seinen Aufruf.
    • Wenn inArray ein Array im Stapel erstellt wurde, ist auch das Aufrufen von delete ein Problem. delete kann nur im Speicher aufgerufen werden, der durch den Aufruf an new zurückgegeben wurde.
+0

Danke für die Antwort Ich verstehe jetzt mehr über Arrays in C++. – kalenpw

1

A = inArray; ist nicht zu tun, was Sie denken, es tut. Diese Zeile führt nicht Kopie inArray in den Speicher, den Sie für A zugewiesen haben. Stattdessen wird A geändert, um auf einen neuen Speicherort (die Adresse inArray) zu zeigen, wodurch der zuvor zugewiesene Speicher undicht wird. Später, wenn Sie delete auf A anrufen, werden Sie versuchen, Speicher unter inArray Adresse zu befreien.

Wenn Sie nur ein Array kopieren möchten, können Sie so etwas wie

A = new int[inArraySize]; 
for (i = 0; i < inArraySize; ++i) 
    A[i] = inArray[i]; 

Oder noch besser, mit std::copy tun:

std::copy(inArray, inArray + inArraySize, A); 
+0

@ acraig5075 Sie schlagen Minute, aber danke für die Antwort – kalenpw

Verwandte Themen