3 votes

Comment puis-je autoriser la réentrée/le passage d'un constructeur singleton dans VS2017 ?

J'ai porté une application c++ de Visual Studio 2013 à Visual Studio 2017. Mis à part la pléthore de nouveaux avertissements que j'ai dû corriger, la compilation et la liaison se sont bien déroulées.

Cependant, lorsque en cours d'exécution l'application, elle " calait " lorsqu'elle essayait de rentrer dans le constructeur d'un singleton (lorsque les appels de fonction successifs forment une boucle vers le constructeur). Il semble que ce comportement était acceptable dans VS2013, mais n'est plus valable dans VS2017. Il n'y a pas de message d'erreur.

Je suis conscient de toutes les mauvaises choses liées aux singletons, et qu'il ne devrait au moins pas y avoir de boucles. La question n'est pas là.

Existe-t-il un moyen d'indiquer au compilateur VS2017 que je souhaite me tirer une balle dans le pied et autoriser le même comportement que celui qui existait dans VS2013 ?

Je n'ai pas accès au code à l'origine de ce comportement car il provient d'une bibliothèque tierce. C'est pourquoi je ne peux malheureusement pas le "réparer".

Voici un exemple qui fonctionne dans VS2013, mais qui ne fonctionne pas dans VS2017 :

main.cpp

#include "Singleton.h";

int 
main( void )
{

  std::cout << "let's do this!" << std::endl;
  int two = Singleton::GetReference().getTwo();
  std::cout << "ok" << std::endl;
  return 0;
}

Singleton.h

#pragma once

class Stuff;

class Singleton
{
public:
  static Singleton& GetReference();

  int getTwo() { return 2; }

private:
  Singleton();

  Stuff* stuff;
};

Singleton.cpp

#include "Singleton.h"
#include "Stuff.h"

Singleton& 
Singleton::GetReference() { 
  static Singleton theInstance; 
  return theInstance; 
}

Singleton::Singleton()
{
  stuff = new Stuff();
}

Stuff.h

#pragma once

class Stuff
{
public:
  Stuff();
private:
  int two;
};

Stuff.cpp

#include "Stuff.h"
#include "Singleton.h"

Stuff::Stuff()
{ 
  two = Singleton::GetReference().getTwo();
}

Dans le code ci-dessus, lors du débogage pas à pas, la première fois que nous arrivons sur la ligne static Singleton theInstance; fonctionnera comme prévu, mais la seconde fois, une F11 ira dans le fichier thread_safe_statics.cpp dans la méthode extern "C" void __cdecl _Init_thread_header(int* const pOnce) . A Shift+F11 quittera la méthode et le programme attendra indéfiniment à la ligne spécifiée (observé lors de la mise en pause du programme depuis le débogueur).


PS

Ce problème se produit probablement aussi dans Visual Studio 2015, car la documentation liée à la réponse acceptée mentionne VS2015.

2voto

mksteve Points 3337
/Zc:threadSafeInit-

La page générale "Conformité" est MSDN : Conformité qui détaille les nouvelles fonctionnalités que vous pouvez désactiver.

J'avais besoin du code de sizedDealloc, où mon nouveau compilateur créait un nouvel opérateur sized pour une bibliothèque qui brisait les attentes des anciens compilateurs.

Comme il s'agit d'un drapeau de compilation, au moins une partie du code sera sous votre contrôle, et vous devriez être en mesure de démêler la bête.

Le constructeur Stuff::Stuff c'est appeler une fonction sur un objet incomplètement construit.

Cela créerait un "comportement indéfini". Si la valeur "2" n'est pas définie jusqu'à la fin du constructeur (par exemple).

Le Singleton doit probablement être divisé en deux, l'un fournissant les premières données statiques (par exemple 2).

Le second qui délivre l'objet retenu Stuff. Stuff ne s'appuierait que sur le premier, ce qui permettrait de sortir de l'impasse.

Alternativement, un second constructeur pour Stuff qui lui indique quel objet utiliser, et qui est appelé à partir de l'objet Singleton::Singleton

L'article du MSDN pour désactiver la "Magic Statics". MSDN : désactiver l'initialisation statique threadsafe

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X