Pergunta

Eu tenho o seguinte código:

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

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

O WideString é uma classe de terceiros, assim como Stringutils. Eles são uma caixa preta para mim. O segundo parâmetro é passado por referência.

Quando eu passo pelo depurador a linha return ret joga um pop -up desagradável (Visual C ++) dizendo que a pilha pode ser corrompida. Após uma cópia de exame mais detalhada da string que é devolvida é bom, mas a exclusão de ret falha. ret contém valor correto antes do retorno.

O que a função de conversão poderia fazer para causar isso? Alguma ideia para consertar?

Atualizar:

  • O projeto em si é uma DLL
  • Stringutils é um lib
  • O projeto é compilado contra CRT multithread (não depuração, não DLL)
  • O programa parece correr bem quando executado fora do Visual Studio
Foi útil?

Solução

  1. Se Stringutils foi compilado separadamente (por exemplo, com uma versão diferente do compilador), você pode ter um conflito no layout do objeto.
  2. Se o Stringutils estiver em uma DLL, você deve garantir que ele e o programa principal sejam compilados para usar a biblioteca padrão em uma DLL. Caso contrário, cada módulo (executável e DLL) terá seu próprio heap. Quando Stringutils tenta brincar com dados na string que foi alocada a partir de uma pilha diferente, coisas ruins acontecem.

Outras dicas

O designer de Stringutils projetou uma API muito ruim. Nenhum dos tipos de biblioteca padrão modelo deve ser usado na interface pública da API. std::string está explodido em linha. Portanto, se o compilador e as bibliotecas que você está usando não for exatamente o mesmo compilador e bibliotecas usadas pelo implementador de Stringutils, os tipos podem e provavelmente serão diferentes. Fundamentalmente, o implementador de Stringutils falhou em separar a interface da implementação.

Uma ilustração do problema. Suponha que você esteja usando o MSVC 9.0 SP1 e estou usando o MSVC 8.0. No meu compilador, a implementação do std :: string pode ser assim:

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

... mas no seu compilador pode parecer diferente:

class string
{
// : :  stuff
private: 

  void* impl_;
};

Se eu escrever uma função da biblioteca:

void DoSomethingWithAString(std::string& str);

... e você chama isso, o sizeof(string) no seu código será diferente do sizeof(string) no meu código. Os tipos não são os mesmos.

Você realmente só tem 2 soluções para o seu problema:

1) [Preferido] Obtenha o implementador de Stringutils para corrigir seu código quebrado.

2) Substitua a biblioteca usada pelo seu compilador para corresponder à biblioteca usada pelo implementador da Stringutil. Você pode conseguir isso usando o mesmo compilador no mesmo nível de patch que o implementador usado, assumindo que ele não substituiu a implementação da biblioteca padrão.

Editar: 3) Uma terceira opção seria parar de usar StringUtils. Honestamente, é provavelmente isso que eu faria.

Do pequeno código que você mostra, suponho StringUtils::ConvertWideStringToUTF8() Leva um std::string& como um segundo parâmetro. Dado isso, não vejo como seu código pode causar uma corrupção de heap.

Observe, no entanto, que a ligação das bibliotecas C ++ em geral só funciona quando o código foi compilado usando o mesmo compilador e as mesmas configurações do compilador.

Seu uso de StringUtils e WideString Faz parecer que você está usando o C ++ Builder. Você está tentando misturar um módulo C ++ Builder e um módulo Visual C ++? Nesse caso, você definitivamente veria os problemas que descreveu.

Você não pode passar um C ++ visual std::string Para uma função do construtor C ++ porque o código do construtor C ++ assumirá que o parâmetro usa o C ++ Builder's std::string definição. As classes podem ter campos diferentes, e os campos que eles têm em comum podem estar em uma ordem diferente.

Mesmo que as classes tenham as mesmas definições, os módulos ainda usarão diferentes gerentes de memória. A função chamada alocará memória para o novo conteúdo da string usando seu gerenciador de memória e o chamador usará seu próprio gerenciador de memória para tentar liberar o conteúdo da string posteriormente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top