Skip to content

Commit 8924dfb

Browse files
committed
Manejo de errores
1 parent 61c00c1 commit 8924dfb

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
layout: post
3+
title: EOF
4+
author: Federico Manuel Gomez Peter
5+
date: 05/05/2021
6+
tags: [correccion, Files]
7+
snippets: none
8+
9+
---
10+
11+
Observar el siguiente ejemplo y reflexionar: ¿qué problema tiene?
12+
13+
```c
14+
int main(int argc, const char *argv[]) {
15+
socket_t skt;
16+
socket_init(&skt);
17+
socket_connect(&skt, argv[1], argv[2]);
18+
// do something
19+
socket_uninit(&skt);
20+
}
21+
```
22+
23+
Como futuros profesionales, debemos contemplar que nuestros programas no siempre van a ir
24+
por el camino feliz de la ejecución. Algo puede _malir sal_ y tenemos la responsabilidad
25+
de que nuestros programas sean lo suficientemente robustos ante fallas inesperadas.
26+
¿Qué pasa si el usuario, al ejecutar el programa, no le pasa ningún argumento?
27+
¿Qué pasaría si el sistema operativo no pudo darme un _file descriptor_?
28+
¿Qué pasaría si no logro conectarme a un servidor, y después quiero hacer
29+
un `socket_send`? Nuestros programas pueden fallar, y debemos chequear que esto no suceda,
30+
y si sucede, abortar la ejecución de forma ordenada, liberando **todos** los recursos solicitados.
31+
32+
```c
33+
#define ARGV_HOSTNAME_INDEX 1
34+
#define ARGV_SERVICE_INDEX 2
35+
#define ARGV_FILEPATH_INDEX 3
36+
#define ARGC_MANDATORY_QUANTITY 4
37+
38+
int main(int argc, const char *argv[]) {
39+
if (argc != ARGC_MANDATORY_QUANTITY) {
40+
fprintf(stderr, "Uso: %s <hostname> <servicio> <path al archivo>\n", argv[0]);
41+
return -1;
42+
}
43+
44+
socket_t skt;
45+
FILE *file;
46+
if (socket_init(&skt) < 0) {
47+
// Como no alloqué nada antes de esta función, no hago nada
48+
// (Se asume que lo que alloque la función socket_init fue liberado si
49+
// tuvo alguna falla interna)
50+
fprintf(stderr, "Falló socket_init (%s)\n", strerror(errno));
51+
return -1;
52+
}
53+
54+
if ( (file = fopen(argv[ARGV_FILEPATH_INDEX], "r")) == NULL) {
55+
fprintf(stderr, "No pude abrir el archivo (%s)\n", strerror(errno));
56+
socket_uninit(&skt);
57+
return -1;
58+
}
59+
60+
if (socket_connect(&skt, argv[ARGV_HOSTNAME_INDEX], argv[ARGV_SERVICE_INDEX]) < 0) {
61+
fprintf(stderr, "No pude conectarme (%s)\n", strerror(errno));
62+
fclose(file);
63+
socket_uninit(&skt);
64+
return -1;
65+
}
66+
67+
// do something
68+
69+
fclose(file);
70+
socket_uninit(&skt);
71+
return 0;
72+
}
73+
```
74+
75+
76+
Cualquiera de estas funciones pueden fallar, y si lo hacen, nos imposibilitaría a continuar la ejecución.
77+
Por esta razon, se chequean errores y se liberan los recursos de forma ordenada. La contra es que
78+
el código se hace mas ilegible. En clases posteriores vamos a ver cómo en C++ podemos tener la misma robustez
79+
que este programa, conservando la legibilidad del primer programa. Mientras tanto, en C nos tenemos que conformar
80+
con esto (en C existen otros métodos para mejorar la legibilidad, pero requieren el uso del infame `goto` y
81+
en la facultad eso es palabra prohibida).

0 commit comments

Comments
 (0)