eu tenho certeza que meu código em é perfeitora089067/ensino/... · 2016-02-09 · meu código em...
TRANSCRIPT
Eu tenho certeza que meu código em C
é perfeito
Guilherme Polo
14 de setembro de 2011
2nd D
raft
``Somebody told me that in basketball you can't hold the ball and run. I got a basketball and tried it and it worked just fine. He obviously didn't understand basketball.’’ Roger Miller
int i;int *x;
x = (int *)malloc(10 * sizeof(int));
for (i = 0; i < 10; i++) { x[i]++;}for (i = 0; i < 10; i++) { printf("%d: %d\n", i, x[i]);}free(x);
2011-247
int i;int *x;
x = (int *)malloc(10 * sizeof(int));
for (i = 0; i < 10; i++) { x[i]++;}for (i = 0; i < 10; i++) { printf("%d: %d\n", i, x[i]);}free(x);
http://c-faq.com/malloc/cast.html
2011-247
int i;int *x;
x = (int *)malloc(10 * sizeof(int));
for (i = 0; i < 10; i++) { x[i]++;}for (i = 0; i < 10; i++) { printf("%d: %d\n", i, x[i]);}free(x);
*x
http://c-faq.com/aryptr/fn33.html
2011-247
int i;int *x;
x = (int *)malloc(10 * sizeof(int));
for (i = 0; i < 10; i++) { x[i]++;}for (i = 0; i < 10; i++) { printf("%d: %d\n", i, x[i]);}free(x);
*x
x[i] nunca foi inicializado
?
2011-247
int i;int *x;
x = (int *)malloc(10 * sizeof(int));
for (i = 0; i < 10; i++) { x[i]++;}for (i = 0; i < 10; i++) { printf("%d: %d\n", i, x[i]);}free(x);
*x
memset(x, 0, 10 * sizeof(*x));
2011-247
int i;int *x;
x = (int *)malloc(10 * sizeof(int));
for (i = 0; i < 10; i++) { x[i]++;}for (i = 0; i < 10; i++) { printf("%d: %d\n", i, x[i]);}free(x);
*x
memset(x, 0, 10 * sizeof(*x));
2011-247
void f(int **x) { if (*x == NULL) { *x = malloc(sizeof(**x)); } **x = 10;}
...
int *x;f(&x);free(x);
2011-247
void f(int **x) { if (*x == NULL) { *x = malloc(sizeof(**x)); } **x = 10;}
...
int *x;f(&x);free(x);
2011-247
void f(int **x) { if (*x == NULL) { *x = malloc(sizeof(**x)); } **x = 10;}
...
int *x;f(&x);free(x);
memória nunca foi alocada
2011-247
void f(int **x) { if (*x == NULL) { *x = malloc(sizeof(**x)); } **x = 10;}
...
int *x;f(&x);free(x);
x = NULL;
2011-247
void f(int **x) { if (*x == NULL) { *x = malloc(sizeof(**x)); } **x = 10;}
...
int *x;f(&x);free(x);
x = NULL;
2011-247
int **x, i, j;
x = malloc(sizeof(int) * 10);for (i = 0; i < 10; i++) { x[i] = malloc(sizeof(int) * 5);}for (i = 0; i < 10; i++) { free(x[i]);}
2011-247
int **x, i, j;
x = malloc(sizeof(int) * 10);for (i = 0; i < 10; i++) { x[i] = malloc(sizeof(int) * 5);}for (i = 0; i < 10; i++) { free(x[i]);}
int*
2011-247
int **x, i, j;
x = malloc(sizeof(int) * 10);for (i = 0; i < 10; i++) { x[i] = malloc(sizeof(int) * 5);}for (i = 0; i < 10; i++) { free(x[i]);}
int*
*x
2011-247
int **x, i, j;
x = malloc(sizeof(int) * 10);for (i = 0; i < 10; i++) { x[i] = malloc(sizeof(int) * 5);}for (i = 0; i < 10; i++) { free(x[i]);}
int*
*x
**x
2011-247
int **x, i, j;
x = malloc(sizeof(int) * 10);for (i = 0; i < 10; i++) { x[i] = malloc(sizeof(int) * 5);}for (i = 0; i < 10; i++) { free(x[i]);}
int*
*x
**x
free(x);
2011-247
int **x, i, j;
x = malloc(sizeof(int) * 10);for (i = 0; i < 10; i++) { x[i] = malloc(sizeof(int) * 5);}for (i = 0; i < 10; i++) { free(x[i]);}
int*
*x
**x
free(x);
2011-247
int i, j, k, l, max, *t;max = 10;t = malloc(max * sizeof(*t));for (i = 0; i < max; i++) t[i] = max - i;k = 0;while (1) { t[k]--; for (j=k-1, l=0; j>=0 && (t[k]-l)>0; j--,l++) t[j]++; ++j; if (t[j] > 0) k = j; else k++; if (k > max) break;}free(t);
2011-247
int i, j, k, l, max, *t;max = 10;t = malloc(max * sizeof(*t));for (i = 0; i < max; i++) t[i] = max - i;k = 0;while (1) { t[k]--; for (j=k-1, l=0; j>=0 && (t[k]-l)>0; j--,l++) t[j]++; ++j; if (t[j] > 0) k = j; else k++; if (k > max) break;}free(t);
permite acessar t[10]
2011-247
int i, j, k, l, max, *t;max = 10;t = malloc(max * sizeof(*t));for (i = 0; i < max; i++) t[i] = max - i;k = 0;while (1) { t[k]--; for (j=k-1, l=0; j>=0 && (t[k]-l)>0; j--,l++) t[j]++; ++j; if (t[j] > 0) k = j; else k++; if (k > max) break;}free(t);
permite acessar t[10] , que é o sentinela
2011-247
int i, j, k, l, max, *t;max = 10;t = malloc(max * sizeof(*t));for (i = 0; i < max; i++) t[i] = max - i;k = 0;while (1) { t[k]--; for (j=k-1, l=0; j>=0 && (t[k]-l)>0; j--,l++) t[j]++; ++j; if (t[j] > 0) k = j; else k++; if (k > max) break;}free(t);
permite acessar t[10] , que é o sentinela
(max + 1)
2011-247
int i, j, k, l, max, *t;max = 10;t = malloc(max * sizeof(*t));for (i = 0; i < max; i++) t[i] = max - i;k = 0;while (1) { t[k]--; for (j=k-1, l=0; j>=0 && (t[k]-l)>0; j--,l++) t[j]++; ++j; if (t[j] > 0) k = j; else k++; if (k > max) break;}free(t);
permite acessar t[10] , que é o sentinela
(max + 1)
t[10] não foi inicializado
2011-247
int i, j, k, l, max, *t;max = 10;t = malloc(max * sizeof(*t));for (i = 0; i < max; i++) t[i] = max - i;k = 0;while (1) { t[k]--; for (j=k-1, l=0; j>=0 && (t[k]-l)>0; j--,l++) t[j]++; ++j; if (t[j] > 0) k = j; else k++; if (k > max) break;}free(t);
(max + 1)<=
2011-247
int i, j, k, l, max, *t;max = 10;t = malloc(max * sizeof(*t));for (i = 0; i < max; i++) t[i] = max - i;k = 0;while (1) { t[k]--; for (j=k-1, l=0; j>=0 && (t[k]-l)>0; j--,l++) t[j]++; ++j; if (t[j] > 0) k = j; else k++; if (k > max) break;}free(t);
(max + 1)<=
2011-247
2011-257
struct s { enum {a, b, c} t; union { int i; } v;};
int i, max = 0;struct s *x = malloc(100 * sizeof(*x));for (i = 0; i < 100; i++) { x[i].t = random() % 3; if (x[i].t == a) x[i].v.i = i;}for (i = 0; i < 100; i++) { max = (x[i].v.i > max) ? x[i].v.i : max;}
...
2011-257
struct s { enum {a, b, c} t; union { int i; } v;};
int i, max = 0;struct s *x = malloc(100 * sizeof(*x));for (i = 0; i < 100; i++) { x[i].t = random() % 3; if (x[i].t == a) x[i].v.i = i;}for (i = 0; i < 100; i++) { max = (x[i].v.i > max) ? x[i].v.i : max;}
...Conteúdo potencialmentenão inicializado
2011-257
struct s { enum {a, b, c} t; union { int i; } v;};
int i, max = 0;struct s *x = malloc(100 * sizeof(*x));for (i = 0; i < 100; i++) { x[i].t = random() % 3; if (x[i].t == a) x[i].v.i = i;}for (i = 0; i < 100; i++) { if (x[i].t == a) max = (x[i].v.i > max) ? x[i].v.i : max;}
...
2011-257
struct s { enum {a, b, c} t; union { int i; } v;};
int i, max = 0;struct s *x = malloc(100 * sizeof(*x));for (i = 0; i < 100; i++) { x[i].t = random() % 3; if (x[i].t == a) x[i].v.i = i;}for (i = 0; i < 100; i++) { if (x[i].t == a) max = (x[i].v.i > max) ? x[i].v.i : max;}
...
Outras recomendações
• Diferentemente dos exemplos exibidos, verifique todos os retornos
• Crie funções (com nomenclatura consistente) que fazem a verificação
• malloc Malloc, scanf Scanf, ...
• Utilize Valgrind não somente para verificar por memory leak
→ →
Valgrind vs.clang + SAFECode 1 #include <stdlib.h> 2 3 int 4 main(void) 5 { 6 int i, *x; 7 8 x = malloc(10 * sizeof *x); 9 for (i = -5; i < 15; i++) {10 x[i] = 0;11 }12 13 return 0;14 }
broken.c
Valgrind$ gcc -Wall -ansi -pedantic -m32 -g -o broken broken.c
$ ./broken
$
Código executou sem problemas!Se a frase do Roger Miller não tinha feito sentido, volte para o começo destes slides e a releia
Valgrind
$ valgrind ./broken<Mensagem inicial removida>==17920== ==17920== Invalid write of size 4==17920== at 0x1F6D: main (broken.c:10)==17920== Address 0x24f34c is not stack'd, malloc'd or (recently) free'd==17920== <Continua ..>
Valgrind
$ valgrind ./broken<Mensagem inicial removida>==17920== ==17920== Invalid write of size 4==17920== at 0x1F6D: main (broken.c:10)==17920== Address 0x24f34c is not stack'd, malloc'd or (recently) free'd==17920== <Continua ..>
PID
x[i] = 0;
estamos mexendo em algo que não nos pertence
Valgrind<Continua ..>==17959== ==17959== HEAP SUMMARY:==17959== in use at exit: 360 bytes in 8 blocks==17959== total heap usage: 8 allocs, 0 frees, 360 bytes allocated==17959== ==17959== LEAK SUMMARY:==17959== definitely lost: 40 bytes in 1 blocks==17959== indirectly lost: 0 bytes in 0 blocks==17959== possibly lost: 0 bytes in 0 blocks==17959== still reachable: 320 bytes in 7 blocks==17959== suppressed: 0 bytes in 0 blocks<Continua ..>
Valgrind<Continua ..>==17959== ==17959== HEAP SUMMARY:==17959== in use at exit: 360 bytes in 8 blocks==17959== total heap usage: 8 allocs, 0 frees, 360 bytes allocated==17959== ==17959== LEAK SUMMARY:==17959== definitely lost: 40 bytes in 1 blocks==17959== indirectly lost: 0 bytes in 0 blocks==17959== possibly lost: 0 bytes in 0 blocks==17959== still reachable: 320 bytes in 7 blocks==17959== suppressed: 0 bytes in 0 blocks<Continua ..>
código nãochamou free
Valgrind<Continua ..>==17959== Rerun with --leak-check=full to see details of leaked memory==17959== ==17959== For counts of detected and suppressed errors, rerun with: -v==17959== ERROR SUMMARY: 10 errors from 1 contexts (suppressed: 0 from 0)
Valgrind<Continua ..>==17959== Rerun with --leak-check=full to see details of leaked memory==17959== ==17959== For counts of detected and suppressed errors, rerun with: -v==17959== ERROR SUMMARY: 10 errors from 1 contexts (suppressed: 0 from 0)
Quais posições invalidas foram acessadas ?-5, -4, -3, -2, -1, 10, 11, 12, 13, 14. Total: 10
clang + SAFECode$ clang -g -fmemsafety -o broken.o -c broken.c$ clang -g -o broken broken.o -lsc_dbg_rt \ -lpoolalloc_bitmap -lstdc++$ ./broken<Próximo slide..>
clang + SAFECodeSAFECode:Violation Type 0x6 when accessing 0x10010022c at IP=0x100001ca8
=======+++++++ SAFECODE RUNTIME ALERT +++++++======== Error type : Load/Store Error= Faulting pointer : 0x10010022c= Program counter : 0x100001ca8= Fault PC Source : broken.c:10== Object allocated at PC : 0x100001b2d= Allocated in Source File : broken.c:8= Object allocation sequence number : 1= Object start : 0x100100240= Object length : 0x28
<E várias outras parecidas para cada acesso inválido>
clang + SAFECodeSAFECode:Violation Type 0x6 when accessing 0x10010022c at IP=0x100001ca8
=======+++++++ SAFECODE RUNTIME ALERT +++++++======== Error type : Load/Store Error= Faulting pointer : 0x10010022c= Program counter : 0x100001ca8= Fault PC Source : broken.c:10== Object allocated at PC : 0x100001b2d= Allocated in Source File : broken.c:8= Object allocation sequence number : 1= Object start : 0x100100240= Object length : 0x28
<E várias outras parecidas para cada acesso inválido>
estamos mexendo em algo que não
nos pertence
endereço que não deveria ter sido
acessado
onde deu problema
clang + SAFECodeSAFECode:Violation Type 0x6 when accessing 0x10010022c at IP=0x100001ca8
=======+++++++ SAFECODE RUNTIME ALERT +++++++======== Error type : Load/Store Error= Faulting pointer : 0x10010022c= Program counter : 0x100001ca8= Fault PC Source : broken.c:10== Object allocated at PC : 0x100001b2d= Allocated in Source File : broken.c:8= Object allocation sequence number : 1= Object start : 0x100100240= Object length : 0x28
<E várias outras parecidas para cada acesso inválido>x = malloc(10 * sizeof *x);0x28 = (40)10 bytes foram alocados
endereço inicial da região alocada
clang + SAFECodeSAFECode:Violation Type 0x6 when accessing 0x10010022c at IP=0x100001ca8
=======+++++++ SAFECODE RUNTIME ALERT +++++++======== Error type : Load/Store Error= Faulting pointer : 0x10010022c= Program counter : 0x100001ca8= Fault PC Source : broken.c:10== Object allocated at PC : 0x100001b2d= Allocated in Source File : broken.c:8= Object allocation sequence number : 1= Object start : 0x100100240= Object length : 0x28
<E várias outras parecidas para cada acesso inválido>
Valgrind vs.clang + SAFECode
De modo geral, a segunda opção fornece alguns detalhes extras para casos de acessos fora dos limites
Para acessos inválidos dentro dos limites, a versão atual não reporta erros
O exemplo utilizado não contempla esta situação
``Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.’’ Donald E. Knuth
struct node { struct node *next; };
voidappend(struct node *l, struct node *n){ while (l->next) { l = l->next; } l->next = n;}
... int i;struct node *l = calloc(1, sizeof(*l));
for (i = 0; i < 1000000; i++) append(l, calloc(1, sizeof(*l));...
2011-247
struct node { struct node *next; };
voidappend(struct node *l, struct node *n){ while (l->next) { l = l->next; } l->next = n;}
... int i;struct node *l = calloc(1, sizeof(*l));
for (i = 0; i < 1000000; i++) append(l, calloc(1, sizeof(*l));...
( )
2011-247
struct node { struct node *next; };
void append(struct node *l, struct node *n){ while (l->next) { l = l->next; } l->next = n; }
...int i;struct node *l = calloc(1, sizeof(*l));
for (i = 0; i < 1000000; i++) append(l, calloc(1, sizeof(*l));...
( )
struct node *
return n;
2011-247
struct node { struct node *next; };
void append(struct node *l, struct node *n){ while (l->next) { l = l->next; } l->next = n; }
...int i;struct node *l = calloc(1, sizeof(*l));
for (i = 0; i < 1000000; i++) append(l, calloc(1, sizeof(*l));...
( )
struct node *
return n;
struct node *end = l;
end2011-247
struct node { struct node *next; };
void append(struct node *l, struct node *n){ while (l->next) { l = l->next; } l->next = n; }
...int i;struct node *l = calloc(1, sizeof(*l));
for (i = 0; i < 1000000; i++) append(l, calloc(1, sizeof(*l));...
struct node *
return n;
struct node *end = l;
end
end =
2011-247
struct node { struct node *next; };
void append(struct node *l, struct node *n){ while (l->next) { l = l->next; } l->next = n; }
...int i;struct node *l = calloc(1, sizeof(*l));
for (i = 0; i < 1000000; i++) append(l, calloc(1, sizeof(*l));...
struct node *
return n;
struct node *end = l;
end
end =
2011-247