Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 168 additions & 0 deletions README.es-ES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@


# Introducción

*reftrack* es un plugin de GCC para el lenguaje C que realiza un seguimiento de las referencias a objetos asignados, aunque también podría utilizarse para otros fines mediante la escritura de funciones personalizadas.

## Requisitos mínimos

- GCC: \>= 12.3 Otras versiones de GCC podrían funcionar, pero las pruebas con la versión 9.3 mostraron que GCC encuentra un error interno del compilador en `-O2` o `-O3` en algunos casos de prueba.
- make: \>= 4.2.1

## Instalación

Descomprima el paquete de fuentes y ejecute `make install` para instalar el plugin de gcc. Puede pasar un valor para `DESTDIR` si necesita empaquetarlo.

## Prueba de verificación

``` bash
$ cd testcases
$ make run
```

Todos los casos de prueba deben aprobarse.

## Integración

Agregue
`-fplugin=/usr/lib64/reftrack.so -I/usr/include/reftrack -fplugin-arg-reftrack-addref=reftrack_addref
-fplugin-arg-reftrack-removeref=reftrack_removeref` a `CFLAGS`.
Estos son los argumentos mínimos requeridos.

## Argumentos del plugin

- addref función predeterminada de addref.
- removeref función predeterminada de removeref.

Estas dos funciones deben tener una firma similar a `void fn(const void *const);` y solo deben especificarse en casos donde se prefiera una implementación personalizada de administración de memoria.

## Uso

El primer paso es etiquetar la estructura que necesita ser seguida.

``` c
struct S;
static void S_addref(const struct S *const);
static void S_removeref(const struct S *const);
struct __attribute__((__reftrack__(S_addref, S_removeref))) S {
int foo;
char bar;
};
```

Las funciones `S_addref` y `S_removeref` pueden tener cualquier nombre, siempre que sus firmas sean exactamente iguales a las del ejemplo anterior.

Resulta tedioso escribir estas declaraciones para cada estructura que debe seguirse, por lo que se ha proporcionado la macro `REFTRACK_STRUCT` que simplifica las declaraciones a la forma que se muestra a continuación.

``` c
REFTRACK_STRUCT(S) {
int foo;
char bar;
};
REFTRACK_EPILOG(S)
```

`REFTRACK_EPILOG(S)` es una macro que proporciona definiciones predeterminadas para `S_addref()` y `S_removeref()`. Si desea llamar a un destructor antes de que el objeto sea liberado, utilice la macro `REFTRACK_EPILOG_WITH_DTOR(S)`.

## Transformaciones

El plugin transforma el código C original siempre que encuentra declaraciones que involucran punteros a estructuras a las que se les ha aplicado el atributo *reftrack*.

### Asignaciones

``` c
typedef struct S S;
S *p = ... , *q = ...;
p = q;
```

se transforma en

``` c
typedef struct S S;
S *p = ... , *q = ...;
S_addref(q);
S_removeref(p);
p = q;
```

### Llamadas a funciones

``` c
S *p = ...;

void print_S(S *sp){
stat1;
stat2;
}
print_S(p);

```

se transforma en

``` c
S *p = ...;

void print_S(S *sp){
stat1;
stat2;
S_removeref(sp);
}
S_addref(p);
print_S(p);
```

### Valores de retorno

``` c
S *p = ...;
S *get_obj(int);

p = get_obj(123);
```

se transforma en

``` c
S *p = ...;
S *get_obj(int);

S_removeref(p);
p = get_obj(123);
S_addref(p);

```

## Recolección de basura

Una de las motivaciones detrás del desarrollo de este plugin es implementar la recolección de basura para el lenguaje de programación C que sea compatible de forma nativa con el compilador. La instrumentación de *addref* y *removeref* facilita la implementación de un GC basado en conteo de referencias en lugar de un GC de marcado y barrido, y se proporciona una implementación de ejemplo en *hrcmm.h*.

Las funciones *`rc_malloc()`* y *`rc_calloc()`* son envoltorios para las funciones estándar *`malloc()`* y *`calloc()`* que anteponen un encabezado pequeño a la asignación del objeto al solicitar memoria extra para dicho encabezado. El encabezado contiene el conteo de referencias y, opcionalmente, el nombre del archivo y el número de línea donde se realizó la asignación. De manera similar, *`rc_realloc()`* y *`rc_free()`* son envoltorios para *`realloc()`* y *`free()`*.

Nota: En casi todos los casos, no es necesario llamar a *`rc_free()`* directamente.

## Macros

- `REFTRACK_STRUCT(X)` Declara las funciones `X_addref()` y `X_removeref()`
- `REFTRACK_EPILOG(X)` Define las funciones `X_create()`, `X_addref()` y `X_removeref()`
- `REFTRACK_EPILOG_WITH_DTOR(X)` Igual que `REFTRACK_EPILOG(X)`, pero llama a `X_destroy()` antes de llamar a `free()`. El programador debe proporcionar una definición para `X_destroy()`.
- `REFTRACK_DEBUG` Imprime la ubicación de la asignación y liberación de objetos de memoria. Utiliza espacio adicional en el objeto asignado.
- `REFTRACK_COUNT(p)` Devuelve el conteo de referencias del puntero dado.

# Destructores

Los destructores son funciones especiales que se invocan en un objeto cuando su conteo de referencias es cero y está a punto de ser liberado. Deben tener la firma `REFTRACK_DESTRUCTOR_FN void X_destroy(struct X *const)`

## Funciones de heap

Las funciones que modifican los atributos o el tamaño de una memoria asignada, como *`realloc()`*, deben etiquetarse con `REFTRACK_HEAP_FN`. Este atributo solo es útil si está implementando una solución de GC personalizada. En todos los demás casos, puede no ser necesario.

## Uso dentro del kernel de Linux

En desarrollo. Probado contra el árbol de staging.

## Limitaciones

- Actualmente no se admite el uso de matrices de punteros rastreados. Consulte el ejemplo *array2.c* en el directorio `testcases` para ver una forma de manejarlos.
- El plugin no puede distinguir los punteros que contienen una dirección a un objeto en la pila versus el heap. El uso de una marca en el encabezado adjunto al objeto asignado mitiga este problema en la mayoría de los casos, a costa de un almacenamiento adicional.