logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog


Desafios aos Caçadores de Bugs

Enquanto escrevia a parte 2 sobre sincronização, encontrei um bug na utilização das funções Win32 na parte 1. Qual é o bug?


Em 13/09/2008 06:08, por Rodrigo Strauss


  
 
 
Comentários
Suzuki | website | em 16/09/2008 | #
Apesar de ser um erro mais conceitual do que de programação em si, a chamada a CreateThread no bloco:

for(DWORD a = 0 ; a < threadCount ; a++)
threads.push_back(CreateThread(NULL, NULL, &WorkerThread, &info, NULL, &dwThreadID));

Não está muito correta, apesar de NULL geralmente ser um define para 0, o segundo e o penúltimo parâmetros da função não são ponteiros, e sim o tamanho da stack da nova thread (0 quer dizer o tamanho padrão do processo) e flags de criação (0 quer dizer que a thread começa a rodar assim que é criada), respectivamente. Mesmo sendo os valores literais 0 e 0, os parâmetros mais comuns à chamadas de CreateThread, o conceito de que NULL é um ponteiro faz a chamada realizada no código estar "errada".

Se o erro não for esse, acredito que seja conceitual, porque o programa funciona (para seu propósito de "não funcionar"), não?!

Como cheguei aqui? Kbloc Vacavoa compartilhou este post no Google Reader ;]
Rodrigo Strauss | website | em 16/09/2008 | #
Não é isso, é um bug mesmo, que faz com que o resultado seja bem diferente do esperado.
Eduardo | em 17/09/2008 | #
O problema esta no WaitForMultipleObjects. Examinando a documentação o número máximo de handles é definido por MAXIMUM_WAIT_OBJECTS (buscando qual é o valor encontrei 67) e como se esta criando 100, um valor maior do que o suportado, ocorre um erro 87 e conseqüentemente o programa não funciona como deveria.
Fernando Roberto | website | em 17/09/2008 | #
//-f--> Os comentários que começarem com esse "f"
// é um cacuete meu e servirá para fazer os
// comentários a respeito do bug que espero
// ter encontrado.

void AddAfter(NODE* node, T data)
{
//-f--> Pelo nome deste método, estou admitindo que
// posso utilizá-lo para inserir um nó após qualquer
// outro nó existente, e não somente após o rootNode_
// como é utilizado neste exemplo.
//
// AddAfter(&rootNode_, data);

//-f--> Na linha seguinte é alocado o registro que deverá
// ganhar um lugar na lista ligada (lembre-se dele)
NODE* newNode = new NODE();

//
// primeiro item?
//

//-f--> Seguindo meu comentário anterior, para detectar se
// o elemento que estou inserindo agora é o primeiro,
// eu deveria fazer o teste da linha seguinte utilizando
// a variável rootNode_ e não utilizando o parâmetro
// node, que neste exemplo é sempre o rootNode_.
// Se um parâmetro tivesse sempre que ter o mesmo valor,
// então não deveria ser um parâmetro.

//if(node->next == NULL)
if (node == &rootNode_ && node->next == NULL)
{
//-f--> Desta forma, teriamos que mudar este ASSERT também

//ASSERT(node->previous == NULL && node == &rootNode_);
ASSERT(node->previous == NULL);

//-f--> Aqui deveriamos colocar o novo nó na lista que foi
// alocado no inicio deste método (lembra dele?) e não
// o próprio nó passado como parâmetro

//node->next = node->previous = node;
node->next = node->previous = newNode;

//-f--> Aqui imagino que deveriamos vincular o dado que
// veio como parâmetro ao novo nó alocado.

//node->data = data;
newNode->data = data;
return;
}
else
{
//
// refaz todos os links, para que o nó inserido
// fique entre o nó passado como parâmetro
// e o próximo
//

//-f--> Aqui parece que está tudo certo
newNode->next = node->next;
node->next = newNode;
newNode->previous = node;
newNode->next->previous = newNode;

newNode->data = data;
}

//-f--> Uma última observação aqui seria referente ao uso
// de rootNode_.data.
// Pelo que foi visto neste método, o rootNode_.data
// nunca terá um dado associado a ele, pois as
// associações são sempre feitas como mostra abaixo:
//
// newNode->data = data;
//
// Vou desconsiderar que teremos um espaço do tipo T
// que nunca será utilizado, afinal isso é apenas
// um exemplo.
// Mas o método Dump mostra o rootNode_.data e o
// método Count o conta como um registro válido.
// Assim temos uma ambiguidade aqui. Não sei se o
// erro está em não utilizar o rootNode_.data ou
// se o erro está em levá-los em consideração nos
// métodos Dump e Count.
count_++;
}

//-f--> Não sou de ficar caçando bugs nos posts dos outros,
// mas o convite foi tentador. Espero ter acertado :-)
//
// PS: Sou irmão do Kabloc ;-)
Wander | em 19/09/2008 | #
No caso em que

if(node->next == NULL)

For verdadeiro, temos um memory leak?

Além disso, count_ não é atualizado também...

PS: acabei colocando minha resposta no post errado.

Rodrigo Strauss | website | em 08/10/2008 | #
"bug na utilização das funções Win32"

:-)
rebarba rebarba
  ::::