Eu não tenho como testar agora, mas eu lembro de uma mensagem neste fórum dizendo que o valgrind tinha problemas com threads.
EDIT: Pesquisando, o problema não era do valgrind com threads, mas alguma coisa com o valgrind de modo geral, que eu não consegui reproduzir na época em nenhuma circunstância. Por sinal, tinha sido um tópico aberto por você.
Boa noite Paulo, tudo bom? Lembro de você naquele post. :D
O código não tem threads por enquanto e ele rodou fora do valgrind(aquelas linhas eram fora dele), o mutex é alocado dinamicamente, decidi deixar o código mais enxuto e usar std::string em vez de std::mutex(para descartar ser um problema do mutex), removi as operações e ele apresenta o mesmo erro a não ser que você faça sobrecarga do operador de atribuição, segue:
#include <iostream>
#include <string>
//#define RESOLVER_PROBLEMA 1
class Teste
{
private:
std::string *string;
public:
Teste();
Teste(const Teste &teste);
~Teste();
#ifdef RESOLVER_PROBLEMA
void operator = (const Teste &teste);
#endif
};
Teste::Teste()
{
this->string = new std::string();
}
int main()
{
Teste teste;
for ( size_t posicao = 0, posicao_maximo = 1000000;
posicao_maximo > posicao;
posicao++ )
{
teste = Teste();
}
return 0;
}
Parece ser uma característica da linguagem(C++), estou consertando minhas classes para escapar desse problema. Para solucionar é só descomentar a linha 4.
O Paulo já matou a charada, olhe novamente.
C++ já prevê um operador de atribuição, para uma classe definida. O operador=(cost Test&) provido pelo compilador, copia cada membro do objeto passado por referencia, para a instância this. No sua classe Test, é copiado um ponteiro, logo, string de this recebe string da referência passada por parâmetro, mas não desaloca ela, antes de atribuir.
Sabendo isso, no seu loop é instanciado um objeto temporário a cada o iteração, que passa o ponteiro de string para o objeto Test declarado no incio de main. Após a atribuição, a string original irá apontar para o mesmo local que a string do objeto temporário, e ainda, o ponteiro original está perdido. O segundo problema está nos objetos temporários, cada um chama seu destrutor no final de cada iteração, o destrutor chama delete sobre a string, porém essa mesma string foi atribuída ao objeto anterior, logo, seu string do Test incial, aponta para um ponteiro inválido. No final da main(), o destrutor do Test será invocado, porém, por ter atribuído string de um objeto temporário, que já foi deletado, o destrutor acaba chamado novamente delete sobre mesmo ponteiro. Em ambos os casos, acessar ponteiro inválido e double free, possuem comportamento indefinido, segundo o padrão C++, no teu caso segment fault.
Outra coisa que notei, estas sobrecarregado o construtor por cópia, mas está utilizando o artifício de delegação de construtor, nesse caso, chama o construtor padrão, antes de chamar o construtor de cópia.