Domanda

Ho il seguente codice:

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

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

WideString è una classe di terze parti, così sono StringUtils. Loro sono una scatola nera per me. Secondo parametro è passato per riferimento.

Quando faccio un passo attraverso il debugger la linea return ret getta un popup brutto (Visual C ++) dicendo che heap potrebbe essere danneggiato. Su più vicino copia dell'esame della stringa che viene restituita è OK, ma la cancellazione di ret fallisce. ret contiene il valore corretta prima di ritorno.

Che cosa potrebbe la funzione di conversione eventualmente fare per causare questo? Tutte le idee per risolvere?

Aggiornamento:

  • Progetto stesso è una dll
  • StringUtils è un lib
  • Progetto è compilato contro multithread CRT (non di debug, non dll)
  • programma sembra funzionare bene quando eseguito al di fuori di Visual Studio
È stato utile?

Soluzione

  1. Se StringUtils stato compilato separatamente (per esempio, con una versione del compilatore diverso), si può avere un conflitto nel layout oggetto.
  2. Se StringUtils è in una DLL, è necessario assicurarsi che sia esso e il programma principale sono compilate per utilizzare la libreria standard in una DLL. In caso contrario, ogni modulo (eseguibile e DLL) avrà il suo mucchio. Quando StringUtils cerca di giocare con i dati nella stringa che è stato assegnato da un mucchio di diverso, succedono cose brutte.

Altri suggerimenti

Il progettista di StringUtils progettato un pessimo API. Nessuno dei tipi di libreria standard su modelli deve essere usato in interfaccia pubblica della API. std::string è saltato fuori linea. Quindi, se il compilatore e le librerie che si sta utilizzando non è esattamente lo stesso compilatore e le librerie utilizzato dal implementatore StringUtils, i tipi possono e probabilmente sarà diverso. Fondamentalmente, l'implementor di StringUtils non è riuscito a separare l'interfaccia dalla il implementazione.

Un esempio del problema. Si supponga di utilizzare MSVC 9.0 SP1 e sto usando MSVC 8.0. Sul mio compilatore, l'implementazione di std :: string potrebbe essere simile a questo:

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

... ma sul vostro compilatore potrebbe avere un aspetto diverso:

class string
{
// : :  stuff
private: 

  void* impl_;
};

Se scrivo una funzione di libreria:

void DoSomethingWithAString(std::string& str);

... e tu lo chiami, il sizeof(string) nel codice sarà diverso rispetto al sizeof(string) nel mio codice. I tipi non sono gli stessi.

È davvero solo 2 soluzioni al problema:

1) [preferito] Prendi l'implementor di StringUtils per fissare il suo codice rotto.

2) Sostituire la libreria utilizzata dal compilatore per abbinare la libreria utilizzata da implementazioni di StringUtil. Potreste essere in grado di ottenere questo risultato utilizzando lo stesso compilatore allo stesso livello patch come implementor utilizzato, ammesso che non ha sostituito l'implementazione della libreria standard.

EDIT: 3) Una terza opzione sarebbe quella di smettere di usare StringUtils. Onestamente questo è probabilmente quello che avrei fatto.

Da quel poco che il codice si mostra, suppongo StringUtils::ConvertWideStringToUTF8() prende un std::string& come secondo parametro. Dato che, non vedo come il codice può causare un danneggiamento di heap.

Si noti, tuttavia, che il collegamento di librerie C ++, in generale, funziona solo quando alls il codice è stato compilato usando lo stesso le stesse impostazioni del compilatore compilatore e.

L'utilizzo del StringUtils e WideString lo fa apparire come si sta utilizzando C ++ Builder. Stai cercando di mescolare un modulo C ++ Builder e un modulo di Visual C ++? Se è così, allora si sarebbe sicuramente vedere i problemi che hai descritto.

Non è possibile passare un C ++ visivo std::string a una funzione C ++ Builder, perché il codice C ++ Builder assumerà che il parametro utilizza definizione std::string di C ++ Builder. Le classi potrebbero avere diversi campi, ei campi che hanno in comune potrebbe essere in un ordine diverso.

Anche se le classi hanno le stesse definizioni, i moduli saranno comunque utilizzare diversi gestori di memoria. La funzione chiamata sarà allocare memoria per i nuovi contenuti della stringa che utilizzano il suo gestore di memoria, e il chiamante utilizzerà il proprio gestore di memoria per tentare di liberare il contenuto della stringa in seguito.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top