2010-09-22 17 views
6

Estoy bastante cómodo codificando en lenguajes como Java y C#, pero necesito usar C para un proyecto (debido a llamadas de API de bajo nivel del sistema operativo) y tengo algunas dificultades para manejar los punteros y gestión de memoria (como se ve here)Aprendizaje C procedente de lenguajes OO gestionados

Ahora estoy básicamente escribiendo el código y alimentándolo al compilador para ver si funciona. Eso simplemente no me parece bien. ¿Alguien puede señalarme buenos recursos para que yo entienda los indicadores y la gestión de memoria, provenientes de lenguajes administrados?

+5

Cuando trabajé en C, que fue hace muchos años, mi referencia favorita para C - Kernighan Ritchie - http://www.amazon.com/gp/product/images/0131103628/ref=dp_image_0?ie=UTF8&n = 283155 & s = libros – InSane

+1

Bienvenido al mundo de lo increíble. ¡Prepárese para un rendimiento y una flexibilidad sin precedentes! –

+0

Estoy en el mismo barco que tú, excepto que sustituyo Java y C# con Python y C++. Lo he tratado revisando el código que tenemos en subversión y revisitando la sección sobre punteros y moldes en mis libros de C++ mientras espero que llegue mi copia del "Lenguaje de programación C" de Richie. – xnine

Respuesta

3

Uno de los buenos recursos que ya tomado, así.

Por supuesto que está compilando con todas las advertencias, ¿no?

Aprender haciendo depende en gran medida de la calidad de su compilador y de las advertencias/errores que le da de comer. Lo mejor en ese respecto que encontré en el mundo de linux/POSIX es clang. Muy bien rastrea el origen de los errores y le informa bastante acerca de los archivos de encabezado que faltan.

+0

++ Para "compilar con todas las advertencias activadas". – AlcubierreDrive

1

Algunos consejos:

  • Por varibles por defecto se almacenan en la pila.
  • Varibles se pasan a funciones por valor
  • Se adhieren al mismo proceso para asignar y liberar memoria. por ejemplo, asignar y libre en el mismo la función
  • equivalente de

    Integer i = new Integer(); 
    
    i=5; 
    

de C es

int *p; 

p=malloc(sizeof(int)); 

*p=5; 
  • de asignación de memoria (malloc) pueden fallar, a fin de comprobar el puntero para nulo antes de usarlo
  • Las funciones del sistema operativo pueden fallar y esto puede detectarse mediante los valores devueltos.
1

Aprenda a usar gdb para recorrer su código e imprimir valores de variables (compilar con -g para habilitar los símbolos de depuración).

Utilice valgrind para comprobar si hay pérdidas de memoria y otros problemas relacionados (como corrupción de montón).

1

El lenguaje C no hace nada que no le indique explícitamente que haga.

No hay destructores llamados automáticamente para usted, lo que es bueno y malo (ya que los errores en los destructores pueden ser un problema).

Una manera simple de obtener un comportamiento de destructor algo automático es usar scoping para construir y destruir cosas. Esto puede ponerse feo, ya que los ámbitos anidados mueven cosas más y más hacia la derecha.

if (var = malloc(SIZE)) { // try to keep this line 
    use_var(var); 
    free(var); // and this line close and with easy to comprehend code between them 
} else { 
    error_action(); 
} 
return; // try to limit the number of return statements so that you can ensure resources 
     // are freed for all code paths 

Tratando de hacer que su código como este tanto como sea posible ayudará, aunque no siempre es posible.

Hacer una serie de macros o funciones en línea que inicialicen sus objetos es una buena idea. También realice otro conjunto de funciones que asignen la memoria de sus objetos y la transfieran a sus funciones de inicialización. Esto permite que los objetos asignados localmente y dinámicamente se inicialicen fácilmente. Operaciones similares para funciones similares a las de un destructor también son una buena idea.

El uso de técnicas OO es una buena práctica en muchos casos, y hacerlo en C solo requiere un poco más de tipeo (pero permite un mayor control). Los putters, getters y otras funciones de ayuda pueden ayudar a mantener objetos en estados consistentes y disminuir los cambios que tiene que hacer cuando encuentra un error, si puede mantener la interfaz igual.

También debe consultar la función perror y la errno "variabl".

Por lo general, querrás evitar el uso de excepciones como C. Por lo general, también trato de evitarlas en C++, y solo las uso para errores realmente malos, que se supone que no deben suceder. Una de las principales razones para evitarlos es que no hay llamadas de destrucción hechas mágicamente en C, por lo que los GOTO no locales a menudo se fugarán (o arruinarán) algún tipo de recurso. Dicho esto, hay cosas en C que proporcionan una funcionalidad similar.

La principal excepción como mecanismo en C son las funciones setjmp y longjmp. setjmp se llama desde una ubicación en el código y se pasa una variable (opaca) (jmp_buf) que luego se puede pasar al longjmp. Cuando se realiza una llamada al longjmp, en realidad no regresa a la persona que llama, sino que regresa como el anteriormente llamado setjmp con ese jmp_buf. setjmp devolverá un valor especificado por la llamada al longjmp. Llamadas regulares a setjmp return 0.

Otra excepción como funcionalidad es más específica de la plataforma, pero incluye señales (que tienen sus propios errores).

Otras cosas a tener en son:

El assert macro, que puede ser utilizado para provocar la salida del programa cuando el parámetro (una prueba lógica de algún tipo) falla. Las llamadas al assert desaparecen cuando #define NDEBUG antes que usted #include <assert.h>, por lo que después de la prueba puede eliminar fácilmente las afirmaciones. Esto es realmente bueno para probar punteros NULL antes de desreferenciarlos, así como varias otras condiciones. Si una condición falla, assert intenta imprimir el nombre del archivo fuente y el número de línea de la prueba fallida.

La función abort hace que el programa salga con error sin hacer toda la limpieza que hace la llamada exit. Esto se puede hacer con una señal en algunas plataformas. assert llamadas abort.

Cuestiones relacionadas