logo
Contato | Sobre...        
rebarba rebarba

Rodrigo Strauss :: Blog

follow us in feedly

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 | e-mail | 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 | e-mail | 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"

:-)
Algo a dizer?
Nome:


Site:


E-mail:


Escreva o número vinte e seis:


 Não mostre meu e-mail no site, não serve pra nada mesmo...

Comentário





Os comentários devem ser sobre assuntos relativos ao post, eu provavelmente apagarei comentários totalmente offtopic. Se quiser me enviar uma mensagem, use o formulário de contato. E não esqueça: isso é um site pessoal e eu me reservo o direito de apagar qualquer comentário ofensivo ou inapropriado.
rebarba rebarba
  ::::