hello.c
This commit is contained in:
+10
-2
@@ -4,8 +4,11 @@
|
|||||||
|
|
||||||
- **Fase 2**: buffer dinámico. La Fase 1 está cerrada en Fedora, pero falta
|
- **Fase 2**: buffer dinámico. La Fase 1 está cerrada en Fedora, pero falta
|
||||||
probarla en Windows.
|
probarla en Windows.
|
||||||
- Paso actual: 2.3b, `escpos_buffer_append` (varios bytes: puntero `const` +
|
- Paso actual: 2.3b. `hello.c` ya usa bien `goto cleanup` (punteros a `NULL`
|
||||||
cantidad + `memcpy`). El 2.3a ya está hecho: `buffer_reserve`, `static`, `t` en `nm`.
|
uno por línea, `result`, un solo `return`), sin avisos con gcc ni clang, y
|
||||||
|
Valgrind limpio. Falta `escpos_buffer_append`: el parámetro con la cantidad,
|
||||||
|
`const`, reservar `len + cantidad`, `memcpy` y el comentario de la cabecera.
|
||||||
|
Ahora copia 1 byte (`sizeof *byte`).
|
||||||
- Entorno activo: Fedora 42 nativo (gcc 15.2, clang 20, make 4.4, gdb 17,
|
- Entorno activo: Fedora 42 nativo (gcc 15.2, clang 20, make 4.4, gdb 17,
|
||||||
valgrind 3.26).
|
valgrind 3.26).
|
||||||
|
|
||||||
@@ -36,6 +39,7 @@
|
|||||||
`$@ $< $^`, `.PHONY`.
|
`$@ $< $^`, `.PHONY`.
|
||||||
- Pila y montón, `malloc`/`free`/`realloc`, `NULL`, propiedad de punteros,
|
- Pila y montón, `malloc`/`free`/`realloc`, `NULL`, propiedad de punteros,
|
||||||
tipo opaco, `typedef`, `->`, `uint8_t`/`size_t`, qué tipo usar.
|
tipo opaco, `typedef`, `->`, `uint8_t`/`size_t`, qué tipo usar.
|
||||||
|
- Liberar en caminos de error sin `defer`: patrón `goto cleanup`.
|
||||||
- Depuración: *segfault* (139), `free(): invalid pointer` (134), gdb básico,
|
- Depuración: *segfault* (139), `free(): invalid pointer` (134), gdb básico,
|
||||||
y leer errores e informes de fugas en Valgrind.
|
y leer errores e informes de fugas en Valgrind.
|
||||||
|
|
||||||
@@ -76,6 +80,10 @@
|
|||||||
cambiaba (`buffer->cap`) o que empezaba en 0, y eso daba bucles infinitos.
|
cambiaba (`buffer->cap`) o que empezaba en 0, y eso daba bucles infinitos.
|
||||||
Lo resolvió siguiendo los valores vuelta a vuelta. Seguir pidiéndole trazas
|
Lo resolvió siguiendo los valores vuelta a vuelta. Seguir pidiéndole trazas
|
||||||
a mano.
|
a mano.
|
||||||
|
- Declaraciones múltiples: escribió `escpos_buffer *a, *b, *c = NULL;` creyendo
|
||||||
|
que las tres valían `NULL` (solo la última). Lo detectó clang con
|
||||||
|
`-Wsometimes-uninitialized`. Ahora declara una variable por línea.
|
||||||
|
- Variables locales sin inicializar: creía que valían `NULL` como en Go.
|
||||||
- Impresoras físicas: sin registrar marca y modelo.
|
- Impresoras físicas: sin registrar marca y modelo.
|
||||||
- Confunde puntero colgante ("se pierde") con fuga. Tampoco tenía claro por qué
|
- Confunde puntero colgante ("se pierde") con fuga. Tampoco tenía claro por qué
|
||||||
el slice viejo es seguro en Go tras `append` (el GC no libera el array viejo,
|
el slice viejo es seguro en Go tras `append` (el GC no libera el array viejo,
|
||||||
|
|||||||
@@ -387,6 +387,14 @@ cleanup: /* etiqueta: destino del goto */
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Variables locales sin inicializar = basura.** En Go toda variable nace con
|
||||||
|
su valor cero (`nil`, `0`, `""`). En C, una variable local que no inicializas
|
||||||
|
contiene lo que hubiera antes en esa posición de la pila. Si un `goto` salta
|
||||||
|
por encima de la línea `escpos_buffer *b = escpos_buffer_new();`, esa
|
||||||
|
asignación no se ejecuta y `b` vale cualquier cosa. Pasarla a `free` es
|
||||||
|
comportamiento indefinido. (Las variables **globales** y `static` sí empiezan a
|
||||||
|
cero.)
|
||||||
|
|
||||||
Por qué funciona:
|
Por qué funciona:
|
||||||
|
|
||||||
- Todos los punteros empiezan en `NULL`, y la función de liberar acepta `NULL`
|
- Todos los punteros empiezan en `NULL`, y la función de liberar acepta `NULL`
|
||||||
|
|||||||
+9
-6
@@ -3,12 +3,15 @@
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
int result = 1;
|
||||||
const char *version = escpos_version();
|
const char *version = escpos_version();
|
||||||
|
escpos_buffer *buffer = NULL;
|
||||||
|
escpos_buffer *buffer_a = NULL;
|
||||||
|
escpos_buffer *buffer_b = NULL;
|
||||||
|
|
||||||
printf("%s\n", version);
|
printf("%s\n", version);
|
||||||
|
|
||||||
escpos_buffer *buffer = escpos_buffer_new();
|
buffer = escpos_buffer_new();
|
||||||
if (buffer == NULL) { goto cleanup; }
|
if (buffer == NULL) { goto cleanup; }
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++)
|
for (int i = 0; i < 100; i++)
|
||||||
@@ -17,7 +20,7 @@ int main(void)
|
|||||||
if (err == -1) { goto cleanup; }
|
if (err == -1) { goto cleanup; }
|
||||||
}
|
}
|
||||||
|
|
||||||
escpos_buffer *buffer_a = escpos_buffer_new();
|
buffer_a = escpos_buffer_new();
|
||||||
if (buffer_a == NULL) { goto cleanup; }
|
if (buffer_a == NULL) { goto cleanup; }
|
||||||
uint8_t data[] = {0x1B, 0x40};
|
uint8_t data[] = {0x1B, 0x40};
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@@ -25,7 +28,7 @@ int main(void)
|
|||||||
err = escpos_buffer_append(buffer_a, data);
|
err = escpos_buffer_append(buffer_a, data);
|
||||||
if (err == -1) { goto cleanup; }
|
if (err == -1) { goto cleanup; }
|
||||||
|
|
||||||
escpos_buffer *buffer_b = escpos_buffer_new();
|
buffer_b = escpos_buffer_new();
|
||||||
if (buffer_b == NULL) { goto cleanup; }
|
if (buffer_b == NULL) { goto cleanup; }
|
||||||
uint8_t data_b[300];
|
uint8_t data_b[300];
|
||||||
for (int i = 0; i < 300; i++)
|
for (int i = 0; i < 300; i++)
|
||||||
@@ -36,11 +39,11 @@ int main(void)
|
|||||||
err = escpos_buffer_append(buffer_b, data_b);
|
err = escpos_buffer_append(buffer_b, data_b);
|
||||||
if (err == -1) { goto cleanup; }
|
if (err == -1) { goto cleanup; }
|
||||||
|
|
||||||
return 0;
|
result = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
escpos_buffer_free(buffer);
|
escpos_buffer_free(buffer);
|
||||||
escpos_buffer_free(buffer_a);
|
escpos_buffer_free(buffer_a);
|
||||||
escpos_buffer_free(buffer_b);
|
escpos_buffer_free(buffer_b);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user