Ich versuchte, ein Universitätsproblem zu lösen, indem ich die gegebenen Anweisungen befolgte. Der Code kompiliert, aber es erzeugt eine Warnung über Speicher. Hier ist der Kern des Codes:C++ shared_ptr Vererbungsspeicherprobleme "Bad deallocation"
#include <iostream>
#include <vector>
#include <memory>
using std::vector;
using std::shared_ptr;
using std::make_shared;
class ApsClass {
protected :
double goose;
public :
virtual ~ApsClass() {}
virtual shared_ptr<ApsClass> clone() const = 0;
double GetGoose() const { return goose; }
};
class DerivedClass : public ApsClass {
public :
~DerivedClass() {} // Warning here*
DerivedClass(double goose) { DerivedClass::goose = goose; }
shared_ptr<ApsClass> clone() const override;
};
shared_ptr<ApsClass> DerivedClass::clone() const {
return make_shared<DerivedClass>(goose);
}
class Storage {
vector<shared_ptr<ApsClass>> geese;
public :
Storage() {}
ApsClass *AddApsClass(ApsClass *pok);
void DelApsClass(ApsClass *pok);
};
ApsClass *Storage::AddApsClass(ApsClass *pok)
{
// The instructions stated that the object pointed at by pok has no
// other pointers pointing at it, and should now be "owned" by geese
geese.push_back(shared_ptr<ApsClass>(pok));
return pok;
}
void Storage::DelApsClass(ApsClass *pok)
{
for (int i = 0; i < geese.size(); i++)
if (geese[i] == shared_ptr<ApsClass>(pok)) {
geese.erase(geese.begin() + i);
break;
}
}
int main()
{
Storage Foo;
ApsClass *s = Foo.AddApsClass(new DerivedClass(0.5));
Foo.DelApsClass(s);
return 0;
}
main() ist im Grunde der Code von einem Autotest, ich soll den Rest des Programms ändern, um main() zu machen richtig.
Die Warnung wird in der Destruktordefinition der abgeleiteten Klasse * gemeldet, bei der Übersetzung ins Englische wird lediglich "Unzulässige Zuordnung" angezeigt. Meine Frage ist: Wo und warum tritt dieses Problem im Code auf?
Der Code schneide ich habe aus hat keinen Einfluss auf die Speicherzuweisung (hoffe ich), und wird über autotesting getestet, die ich habe nicht viel Zugang zu. Ein Test Bericht folgend unter dem anderen:
Invalid read of size 8 ...
Address 0x51f0090 is 0 bytes inside a block of size 56 free'd
und
==10216== Jump to the invalid address stated on the next line
==10216== at 0x0: ???
Address 0x0 is not stack'd, malloc'd or (recently) free'd
und
==10216== Process terminating with default action of signal 11 (SIGSEGV)
==10216== Bad permissions for mapped region at address 0x0
==10216== at 0x0: ???
Wenn weitere Details benötigt werden, kann ich hier einige des ursprünglichen Code setzen.
Ich zweite, dass. Sobald ein roher Pointer durch 'shared_ptr' verwaltet wird, sollte der rohe Pointer nicht mehr verwendet werden (außer zur Verbindung mit Legacy-Code, aber in diesem Fall würden Sie' shared_ptr :: get() 'verwenden). Übergeben Sie stattdessen nur das 'shared_ptr' (oder in Fällen, in denen Sie zirkuläre Verweise verhindern müssen, ein' weak_ptr'), um solche Probleme zu vermeiden. – zett42
Ich verstehe. Allerdings ist das Problem jetzt (ich werde dies zur Frage ETA), dass der Code in main() (modifizierter) Code vom Autotest ist. Ich darf die main() hier nicht ändern. – sishke
@sishke Dann zumindest aber ändern 'Gänse [i] == Shared_ptr (pok)' auf 'Gänse [i] .get() == pok' so dass' DelApsClass' nicht schaffen keine 'shared_ptr's . –
immibis