Mostrando las entradas con la etiqueta C. Mostrar todas las entradas
Mostrando las entradas con la etiqueta C. Mostrar todas las entradas

martes, 27 de mayo de 2025

Las buenas maneras de las llamadas recursivas

The Power of 10 Rules (El poder de las 10 reglas) es una guía para código seguro creada en 2006 por Gerard J. Holzmann del Laboratorio de Software Fiable de la NASA/JPL.

Las reglas prohíben ciertas prácticas de codificación en C que dificultan la revisión o el análisis estático del código. Estas reglas son un complemento a las directrices MISRA C y se han incorporado en el mayor conjunto de estándares de codificación de JPL.

Las diez reglas

  1. Restrinja todo el código a construcciones de flujo de control muy simples. No utilice sentencias GOTO, construcciones set jmp o long jmp, ni recursividad directa o indirecta.
  2. Todos los bucles deben tener un límite superior fijo. Debe ser trivialmente posible para una herramienta de comprobación demostrar estáticamente que no se puede superar un límite superior preestablecido en el número de iteraciones de un bucle. Si el límite del bucle no puede demostrarse estáticamente, se considera que se ha infringido la norma.
  3. No utilice la asignación dinámica de memoria después de la inicialización.
  4. Ninguna función debe ser más larga de lo que se puede imprimir en una sola hoja de papel.
  5. Use un mínimo de dos aserciones en tiempo de ejecución por función. Las aserciones siempre deben estar libres de efectos secundarios y deben definirse como pruebas booleanas.
  6. El scope de los datos debe ser el más pequeño posible.
  7. Cada función de llamada debe comprobar los valores de retorno de función no vacíos, y la validez de los parámetros debe comprobarse dentro de cada función.
  8. El uso del preprocesador debe limitarse a los headers y definiciones de macros simples.
  9. El uso de punteros debe estar restringido a un nivel de des referencia. No se permiten punteros a funciones.
  10. Todo el código debe ser compilado, desde el primer día de desarrollo, con todas las advertencias del compilador habilitadas en la configuración más estricta del compilador. Todo el código debe ser comprobado diariamente con al menos un analizador estático de código fuente actualizado, y debe pasar los análisis con cero advertencias.

La primera regla prohíbe el uso de llamadas recursivas. Las normas de la NASA se centran en la robustez de sistemas de tiempo real que son siempre críticos y inaccesibles para mantenimiento: La recursión puede ser impredecible en sistemas embebidos o de tiempo real.El consumo de recursos no acotados (pila/stack), es crítico en hardware con memoria limitada (ej.: satélites, rovers). Dificultad para verificación formal (requerida en software de seguridad crítica).

Recursión Eficiente: Optimización del Compilador

Para hacer que la recursión sea eficiente y segura, los compiladores modernos aplican optimizaciones clave, pero requieren que el código cumpla ciertas condiciones.

Tail-Call Optimization (TCO)

El compilador reemplaza la llamada recursiva por un bucle (jump) si la recursión está en posición de cola (tail position), evitando crecimiento de la pila (stack). La llamada recursiva debe ser la última operación de la función. Compiladores como GCC/Clang la optimizan con -O2 o -O3.

Trampolining (para lenguajes sin TCO nativo)

Transforma la recursión en un bucle usando una estructura intermedia ("trampolín").

Memoization (Cache de Resultados)

Almacena resultados previos para evitar recalcular en recursión múltiple.

Conversión Manual a Iteración

Si el compilador no optimiza, transforma la recursión en un bucle manualmente.

Fuentes:

NASA JPL Institutional Coding Standard for the C Programming Language (2009).

DO-178C (Estándar para software aeronáutico).

Resumen y extractos en el repositorio técnico de la NASA: NASA Technical Reports Server (NTRS) (Busca "JPL C Coding Standard 2009")

Versión similar y pública (JPL Power of Ten Rules): NASA JPL Power of 10 Rules (Reglas clave resumidas).

DO-178C (Estándar para Software Aeronáutico) Documento oficial: Publicado por RTCA (Requiere compra): RTCA DO-178C (Costo aproximado: $200 USD).

Guías gratuitas relacionadas:

FAA Advisory Circular 20-115C (basado en DO-178C): FAA.gov (Busca "AC 20-115C"). 

miércoles, 28 de mayo de 2014

Depreciación de funciones en Visual Studio C/C++

Uno de los problemas que se presenta al actualizar una aplicación en Visual Studio C/C++ es la depreciación de funciones. La motivación de muchos de estos cambios es hacer el código más seguro.



Existen varias maneras de eliminar las advertencias para las funciones obsoletas o depreciadas. Las más sencilla es definir _CRT_SECURE_NO_WARNINGS o usar el pragma warning. Lo más recomendable es usar la versión segura equivalente.

Referencias:


strcpy_s, wcscpy_s, _mbscpy_s

Security Enhancements in the CRT

viernes, 31 de julio de 2009

Eclipse C/C++ Development Toolkit (CDT)

C/C++ development with the Eclipse Platform

HOW TO: Use CDT and MinGW for Eclipse (i.e. develop C/C++ applications in windows)


Paso 1:


Bajar de mingw.org lo siguiente:

Paso 2:

Extraer los archivos al directorio c:\mingw\ y instalar mingw32-make-3.80.0-3.exe en c:\mingw\.

Paso 3:

Agregar c:\mingw\bin a la variable de ambiente de sistema Paths. Verificar con el comando gcc -v .



Paso 4:


Descargar Eclipse e instalarlo.

Paso 5:


Instalar C/C++ Development Toolkit (CDT) usando el menú de actualización Help-> Software Updates -> Find and Install -> Search for new Features to Install.

Paso 6:

Crear un proyecto nuevo file->new ->Managed Make C Project.

Paso 7:


Agregar el archivo main.cc con el siguiente código (para probar la instalación):

#include
#include
using namespace std;

int main()
{
string yourName;

cout << "Enter your name: ";
cin >> yourName;
cout << "Hello " + yourName << endl;
return 0;
}




viernes, 13 de julio de 2007

Minimalist GNU for Windows

MinGW o MinGW32 (Minimalist GNU for Windows) es una implementación de los compiladores GCC para la plataforma Win32, que permite migrar aplicaciones GNU a entornos Windows. Es un derivado de Cygwin en su versión 1.3.3.

MinGW incluye un conjunto de la api de Win32, permitiendo un desarrollo de aplicaciones nativas para esa plataforma, pudiendo generar ejecutables y librerí­as usando la API de Windows.


MinGW fue creado por Colin Peters, el 1 de julio de 1998, compilándolo con Gygwin. La primera versión nativa de MinGW fue realizada por Jan-Jaap van der Heijden, quien también tuvo participación en el proyecto GCC. Mumit Khan estuvo a cargo del mantenimiento del proyecto e incluyo al compilador algunas características propias de Windows. Los archivos de cabecera del API de Windows fueron provistos por Anders Norlander.

Una de las desventajas de MinGW es que los ejecutables que genera son de tamaño más grande que los generados por otros compiladores. Esto ocurre cuando se incluyen los archivos de cabecera estándares de C++ (por ejemplo, #include ), y se debe a que el compilador vincula todas las librerí­as dentro del archivo ejecutable de manera estática.

MinGW incluye MSYS (Minimal SYStem) un shell POSIX/Bourne para ejecutar scripts de configuración usados por make y ./configure

Después de descargar MinGW y MSYS, incluyendo mingw-runtime, w32api, binutils y gcc, gdb y mingw32-make se pueden expandir los archivos de dos formas. Poner el directorio de MinGW dentro de MSYS o instalarlos en directorios distintos y modificar el archivo MSYS /etc/fstab para agregar un apuntador al directorio donde mingw esta instalado.

Para probar la instalación se puede correr el shell de msys y probar el comando de línea

gcc --v

Para habilitar el soporte de IDEs agregar \lib a la variable de entorno LIBRARY_PATH y los subdirectorios bin de y a la variable de entorno PATH
Aplicación de consola:

En un archivo con el nombre hello.c poner el siguiente código:

#include

int main(int argc, char **argv)
{
printf ("Hello\n");
return (0);
}

y compilar con

gcc -c hello.c

y después

gcc -o hello hello.o

Alternativamente

gcc -o hello hello.c

En un archivo con el nombre hello.cpp poner el siguiente código:

#include
int main(int argc, char **argv)
{
std::cout << "Hello" << std::endl;
return (0);
}

y compilar con

g++ -c hello.cpp
g++ -o hello hello.o
Aplicación Windows

En un archivo con el nombre hello.c poner el siguiente código:

#include

int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow)
{
MessageBox (NULL, "Hello", "Hello Demo", MB_OK);
return (0);
}

para crear el ejecutable usar los comandos de linea

gcc -c hello.c

y

gcc -o hello hello.o -mwindows

el parametro -mwindows es necesario para que se incluyan las librerias necesarias para un programa Windows.
dll

En un archivo con el nombre dllfct.h poner el siguiente código:

#ifdef BUILD_DLL
// the dll exports
#define EXPORT __declspec(dllexport)
#else
// the exe imports
#define EXPORT __declspec(dllimport)
#endif

// function to be imported/exported
EXPORT void tstfunc (void);

En un archivo con el nombre dllfct.c poner el siguiente código:

#include
#include "dllfct.h"

EXPORT void tstfunc (void)
{
printf ("Hello\n");
}

En un archivo con el nombre Hello.c poner el siguiente código:

#include "dllfct.h"

int main ()
{
tstfunc ();
return (0);
}

Para crear una dll y un ejecutable que lo use:

gcc -c hello.c
gcc -c -DBUILD_DLL dllfct.c
gcc -shared -o tst.dll -Wl,--out-implib,libtstdll.a dllfct.o
gcc -o hello.exe hello.o -L./ -ltstdll

Se puede especificar el directorio a usar para los includes durante la compilación con

-I/path/to/headers

y las librerias para link:

-L/usr/lib/library

Usualmente no hay necesidad de andar moviendo las librerias.
Archivo .def para un dll

Si tiene un dll llamado file.dll y quiere crear un archivo .def con el nombre file.def,

echo EXPORTS > file.def
nm file.dll | grep ' T _' | sed 's/.* T _//' >> file.def

Para crear una biblioteca con el nombre file.a :

dlltool --def file.def --dllname file.dll --output-lib file.a