Question

Je le code suivant:

std::string F()
{
  WideString ws = GetMyWideString();

  std::string ret;
  StringUtils::ConvertWideStringToUTF8(ws, ret);
  return ret;
}

WideString est une classe tiers, sont donc StringUtils. Ils sont une boîte noire pour moi. Le second paramètre est passé par référence.

Quand je fais un pas dans le débogueur de la return ret ligne lance un popup méchant (Visual C ++) en disant que tas peut-être endommagé. Lors de la copie d'examen plus approfondi de la chaîne qui est renvoyée est OK, mais la suppression de ret échoue. ret contient la valeur correcte avant le retour.

Qu'est-ce que la fonction de conversion pourrait faire pour la cause? Toutes les idées pour fixer?

Mise à jour:

  • Projet lui-même est une dll
  • StringUtils est un lib
  • Le projet est compilé CRT multithread (pas de débogage, non dll)
  • Programme semble fonctionner très bien lorsqu'il est exécuté en dehors de Visual Studio
Était-ce utile?

La solution

  1. Si StringUtils a été compilé séparément (par exemple, avec une autre version du compilateur), vous pouvez avoir un conflit dans la mise en page de l'objet.
  2. Si StringUtils est dans une DLL, vous devez vous assurer que les deux et le programme principal compilé pour utiliser la bibliothèque standard dans une DLL. Dans le cas contraire, chaque module (exécutable et DLL) aura son propre tas. Lorsque StringUtils essaie de jouer avec les données de la chaîne qui a été allouée à partir d'un tas différent, de mauvaises choses arrivent.

Autres conseils

Le designer de StringUtils a conçu une API très pauvre. Aucun des types de bibliothèque standard basé sur un modèle doit être utilisé dans l'interface publique de l'API. std::string est soufflé en ligne. Donc, si le compilateur et les bibliothèques que vous utilisez ne sont pas exactement le même compilateur et les bibliothèques utilisées par le implementor de StringUtils, les types peuvent et seront probablement différents. Fondamentalement, le implementor de StringUtils n'a pas réussi à séparer l'interface de de mise en œuvre.

Une illustration du problème. Supposons que vous utilisez MSVC 9.0 SP1 et je suis en utilisant MSVC 8.0. Sur mon compilateur, la mise en œuvre de std :: string pourrait ressembler à ceci:

class string
{
// : :  stuff
private:
  int someInt_;
  char* someBuf_;
};

... mais sur votre compilateur, il peut être différent:

class string
{
// : :  stuff
private: 

  void* impl_;
};

Si j'écris une fonction de bibliothèque:

void DoSomethingWithAString(std::string& str);

... et vous l'appelez, le sizeof(string) dans votre code sera différent de celui du sizeof(string) dans mon code. Les types ne sont pas identiques.

Vous avez vraiment avez 2 solutions à votre problème:

1) [préféré] Obtenez le implementor de StringUtils pour fixer son code cassé.

2) Remplacez la bibliothèque utilisée par votre compilateur pour correspondre à la bibliothèque utilisée par le réalisateur de StringUtil. Vous pourriez être en mesure d'accomplir ceci en utilisant le même compilateur au même niveau de patch utilisé le implementor, en supposant qu'il ne remplace pas la mise en œuvre de la bibliothèque standard.

EDIT: 3) Une troisième solution consisterait à cesser d'utiliser StringUtils. Honnêtement, ce qui est probablement ce que je ferais.

D'après ce petit code que vous montrez, je suppose que StringUtils::ConvertWideStringToUTF8() prend std::string& comme second paramètre. Compte tenu de cela, je ne vois pas comment votre code peut provoquer une corruption du tas.

Notez, cependant, que l'enchaînement des bibliothèques C ++ en général ne fonctionne que lorsque alls le code a été compilé en utilisant le même compilateur et les mêmes paramètres du compilateur.

Votre utilisation de StringUtils et WideString fait ressembler à vous utilisez C ++ Builder. Essayez-vous de mélanger un module C ++ Builder et un module Visual C ++? Si oui, alors vous verriez certainement les problèmes que vous avez décrits.

Vous ne pouvez pas passer un Visual C ++ std::string à une fonction C ++ Builder, car le code C ++ Builder suppose que le paramètre utilise la définition de std::string de C ++ Builder. Les classes peuvent avoir des champs différents, et les champs qu'ils ont en commun pourraient être dans un ordre différent.

Même si les classes ont les mêmes définitions, les modules utiliseront encore différents gestionnaires de mémoire. La fonction appelée va allouer de la mémoire pour le nouveau contenu de la chaîne à l'aide de son gestionnaire de mémoire, et l'appelant utilisera son propre gestionnaire de mémoire pour tenter de libérer le contenu de la chaîne plus tard.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top