AV enquanto iteração através hash_map?
-
18-09-2019 - |
Pergunta
_transaction é uma variável membro privado da minha classe, declarada como:
public:
typedef stdext::hash_map<wchar_t*, MyClass*, ltstr> transaction_hash_map;
private:
transaction_hash_map _transactions;
Durante a limpeza Eu estou tentando para percorrer esta lista e liberar todos os objetos ainda não-liberto. No entanto, eu estou recebendo um AV no linha aqui:
for (transaction_hash_map::const_iterator it = _transactions.begin(); it != _transactions.end(); it++)
{
MyClass* item = (MyClass*)it->second;
if (item != NULL)
{
item->End();
delete item;
}
}
Re:? O que é ltstr
private:
struct ltstr
{
enum
{
bucket_size = 8,
min_buckets = 16
};
bool operator()(wchar_t* s1, wchar_t* s2) const
{
return wcscmp( s1, s2 ) < 0;
}
size_t operator()(wchar_t *s1) const
{
size_t h = 0;
wchar_t *p = const_cast<wchar_t*>(s1);
wchar_t zero = L'\0';
while ( *p != zero ) h = 31 * h + (*p++);
return h;
}
};
Os pilha mostra-o dentro do método begin (). Alguma idéia?
Solução
Uma possível coisa que eu posso pensar é que sua classe já foi eliminado em outros lugares antes de tentar percorrer a hash_map, e, assim, começar () estará operando no lixo. Worth um cheque ...
Além disso - como são sua wchar_t * ficando alocados / liberados? O código que você mostrou não parece estar lidando com aqueles. Eu não sei como isso poderia causar problemas em sua malha, mas vale a pena pensar.
Uma coisa menor - você não deve precisar o elenco (MyClass*)
. Os valores da hash_map deve ser daquele tipo de qualquer maneira, por isso é mais agradável para deixar o compilador impor verificações de tipo do que, possivelmente, desvio-los com uma conversão explícita. Isso não deveria estar fazendo alguma diferença aqui embora.
Outras dicas
Como eu entendo que você está verificando o ponteiro contra NULL para os "remanescentes" itens que talvez não tenham sido eliminados ainda. Mas para os itens que você excluir antes de seu estágio de limpeza, você definir o ponteiro para NULL?
Observe que quando você excluir um objeto o ponteiro é não automaticamente definida para NULL. Então, se você não está fazendo que você está tentando excluir o mesmo objeto duas vezes (porque o seu comando if será sempre true), o que poderia causar uma violação de acesso.
O código a seguir é um exemplo que provoca uma dupla eliminação. Ele pode ser corrigido se você remover o comentário da linha que define o ponteiro para NULL.
#include <cstddef>
struct Item {};
int main()
{
Item * p = new Item();
delete p;
//If you don't make the pointer null...
//p = NULL;
if (p != NULL)
//You delete the object twice.
delete p;
}
EDIT: Vejo que você está recebendo o erro exatamente no line. Então, eu estou pensando ...
Ao que parece ter um MyClass que contém um _transactions membro, que é uma tabela hash com MyClass ponteiros como o tipo de dados. Se o código de limpeza é efectuado dentro de uma função membro de MyClass , é possível que você está excluindo (por alguma razão) a MyClass instância que possui o _transactions você está iteração?
Neste caso, você pode obter um erro em isso ++ instrução dentro do para desde o este objeto não existe mais. (Naturalmente, o erro poderia ser em outro lugar também, como na própria exclusão.)
Certifique-se chamar _transactions.clear () após o loop for.