J’ai deux projets, un client de base et une bibliothèque dynamic. Voici ce qui se passe chez le client:
int main() { Scrutinizer scru; scru.Scrutinize(); return 0; }
Dans la DLL, la classe Scrutinizer
est en tant que telle (__declspec (dllexport) et telle omise pour Clarity)
Entête
class ProcessesGenerator; class Scrutinizer { public: Scrutinizer(); ~Scrutinizer(); ProcessesGenerator *ProcGenerator void Scrutinize(); };
La déclaration ProcessesGenerator
de ProcessesGenerator
était «obligatoire» pour éviter toute sorte de référence circulaire.
Constructeur dans un fichier .cpp
Voici comment je l’initialise:
Scrutinizer::Scrutinizer() { ProcGenerator = &ProcessesGenerator(); }
En savoir plus sur cette classe ProcessesGenerator
:
Entête
class ProcessesGenerator { public: ProcessesGenerator(); ~ProcessesGenerator(); WinFinder winFinder; std::vector fooCollec; void GenerateProcesses(); };
ProcessusGenerator.cpp
Constructeur:
ProcessesGenerator::ProcessesGenerator() { //winFinder = WinFinder();//problem will be the same with or without this line fooCollec = std::vector{"one", "two", "three"}; }
Un point d’arrêt dans le constructeur indique que le vecteur est initialisé avec les valeurs choisies.
Fonction problématique:
void ProcessesGenerator::GenerateProcesses() { std::ssortingng foo = "bar"; fooCollec = std::vector{};//read access violation fooCollec.push_back(foo);//read access violation winFinder.SomeVector= std::vector{};//read access violation }
Une fois là, je peux voir que la taille du vecteur est réinitialisée à 0. Toute tentative de réinitialisation ou d’insertion d’un élément entraîne une violation d’access en lecture .Same avec le membre vecotr de son membre WinFinder
. Je suppose que la faille est évidente, mais je ne comprends vraiment pas,
Merci!
Votre problème est avec
Scrutinizer::Scrutinizer() { ProcGenerator = &ProcessesGenerator(); }
Ce que vous faites, c’est prendre l’adresse d’un object temporaire. Cet object sera détruit et la fin de cette ligne et vous restra avec un pointeur qui ne pointe pas vers un object valide.
L’ancienne façon de le réparer serait d’utiliser
Scrutinizer::Scrutinizer() { ProcGenerator = new ProcessesGenerator(); }
Mais maintenant, vous devez implémenter le constructeur de copie, l’opérateur d’affectation de copie et le destructeur. Puisque vous avez un compilateur moderne, vous pouvez plutôt transformer ProcGenerator
une ProcGenerator
std:unique_ptr
, puis Scrutinizer()
devient
Scrutinizer::Scrutinizer() : ProcGenerator(make_unique()) {}
Je voudrais aussi append que &ProcessesGenerator();
ne devrait même pas comstackr. Malheureusement, MSVS a une extension non standard qui permet cette compilation. Vous pouvez activer l’option du compilateur /Za
(appliquer la compatibilité ANSI) et vous obtiendrez alors une erreur telle que
erreur C2102: ‘&’ requirejs la valeur l
La ligne ProcGenerator = &ProcessesGenerator();
crée un ProcessesGenerator
temporaire, prend son adresse puis la place dans votre pointeur ProcGenerator
. Le temporaire est ensuite détruit, laissant des ordures.
Vous souhaitiez probablement l’allouer sur le tas ProcGenerator = new ProcessesGenerator;
mais même dans ce cas, je suggérerais fortement d’utiliser unique_ptr
au lieu d’un pointeur brut.