Ir para o conteúdo
ou

Software livre Brasil

Jonh Wendell

Twitter

redirection forbidden: http://api.twitter.com/1/statuses/user_timeline.rss?screen_name=jwendell -> https://api.twitter.com/1/statuses/user_timeline.rss?screen_name=jwendell

 Voltar a Blog
Tela cheia

free() inconsistencies|inconsistências no free()

19 de Janeiro de 2012, 11:27 , por Software Livre Brasil - 0sem comentários ainda | Ninguém está seguindo este artigo ainda.
Visualizado 5 vezes


Hi, folks!


Last week I was porting a program from uClibc to glibc. Everything went fine, until I found a crash to always happen in a certain part of it. The failure was in a call to the free() function. First thing that came in my head: Why the hell is it crashing now, while it used to run fine on uClibc? I made a simple program that simulates the problem:


Oi gente!


Semana passada tava portando um código compilado em cima da uClibc para glibc. Tudo tranquilo, até que certa parte do programa dava crash. Investigando, vi que a falha acontecia em uma chamada à função free(). Primeira coisa que veio à minha cabeça: porque raios tá dando crash aqui se o mesmo programa, compilado na uClibc roda perfeito? Fiz um programa simples que simula a situação:

#include <stdio.h>
#include <stdlib.h>

typedef struct {
  char *field1;
} s_test;

s_test test = {
  .field1 = NULL
};

int main (int argc, char **argv) {
  s_test *t;

  t = &test;
  free (t);
  t = &test;
  t->field1 = "bug";
  printf ("%s\n", t->field1);

  return 0;
}


Look at line 16. I’m executing a free() in a pointer to a static variable, instead of a pointer in the heap (previously allocated with malloc() or similar). It’s expected a crash here, right? Maybe! Yes, if you’re using glibc. No if you’re using uClibc. The above code works like [not] expected. Weird! Everything we learned at the programming school is ruined now :D !


So, we have a similar code here that have been worked for a long time, exactly because it was compiled and run on top of uClibc. I’ve seen this and other behavior differences between uClibc and glibc. The solution? Change the code to make it portable, not only to make it compile, but also so that it have the same behavior on every platform.


I thought it was a bug in uClibc, but I was told it doesn’t break the standards. In fact, standards say, in that case, the behavior is “undefined”. Ah, standards :) … So, in order to avoid surprises like that, here is what I learned: Always code in the right way, even if it comes with a harder job. Don’t say: “hey, it’s working, let’s deploy it!”.


See you!


Preste atenção na linha 16. Estou executando um free() num ponteiro que aponta para uma variável estática, ao invés de uma variável que foi alocada com malloc() ou similar. Um crash é esperado aqui, certo? Em partes! Usando a glibc, sim. Já com a uclibc, não! O código acima funciona como [não] esperado! Estranho, não? Tudo o que aprendemos na escola de programação vai por água abaixo aqui hehehe.


Então, o que acontece é que temos um código similar aqui e que sempre funcionou, justamente por ser compilado na uclibc. Já vi essa e outras diferenças de comportamento entre a uclibc e a glibc. A solução? Mudar o código para torná-lo portável, não só para que compile corretamente, mas para que tenha os mesmos resultados, independente da plataforma.


A princípio, achei que isso era um bug na uclibc, mas fui apontado que isso não fere “os padrões”. De fato, os padrões dizem que nesse caso, o comportamento é “indefinido”. Ah, padrões :) … Para evitar surpresas do tipo, fica aqui a lição aprendida: programar da forma certa, mesmo que dê um pouco mais de trabalho. Não se acomodar dizendo: “ah, testei aqui e funciona, deixa assim mesmo!” ;)


Bons códigos!


Fonte: http://www.bani.com.br/2012/01/free-inconsistenciesinconsistencias-no-free/

0sem comentários ainda

Enviar um comentário

Os campos são obrigatórios.

Se você é um usuário registrado, pode se identificar e ser reconhecido automaticamente.