tutorial portable para instalar español descargar c gcc cygwin

portable - descargar cygwin para windows 7 64 bits



C programa compilado con cygwin en Windows funciona, fallo de segmentación bajo Linux. ¿Es cygwin GCC ''malo''? (11)

¿Estás haciendo suposiciones específicas de la plataforma, como el tamaño de los tipos de datos , la alineación de la estructura de datos en las struct o la endianidad ?

Para mi clase de Programación 102, se nos pide que entreguemos código C que compila y ejecuta bajo Linux. No tengo suficiente espacio libre en mi disco duro para instalar Linux junto con Windows, así que uso cygwin para compilar mis programas.

El programa más reciente que tuve que dar en compila y funciona bien bajo cygwin. Se compila bien en Linux, pero a mitad de la ejecución produce una falla de segmentación. Le expliqué esto al estudiante graduado que nos da clase y él dijo que la versión de cygwin de GCC permite compilar y ejecutar código más descuidado.

Las pocas referencias que he encontrado a través de google no han sido concluyentes. Un hilo que encontré dijo que la causa del fallo seg en Linux es una pérdida de memoria. ¿Por qué esto no afectaría la versión de cygwin?

Usaría las computadoras de la Universidad, pero no puedo usar Subversion en ellas, lo que obstaculizaría significativamente mis esfuerzos. (Soy nuevo en la codificación y con frecuencia necesito poder volver a las revisiones de X atrás).

¿La versión de cygwin de GCC es realmente más "laxa" con el código que compila? Si es así, ¿hay algún problema obvio que tener en cuenta al codificar? ¿Hay alguna alternativa para poder escribir código que se ejecutará bajo Linux?

Editar

Gracias por las respuestas No fui lo suficientemente explícito en mi publicación original: que había un error en mi código que era algo dado para mí (soy bastante nuevo en la programación, y realmente verde cuando se trata de C, después de todo). Mi TA implicaba que el GCC de cygwin es un compilador menos confiable, que permite ejecutar código mucho más descuidado que el que se encuentra en GNU / Linux. Encontré esto extraño y tuve una búsqueda en Internet, pero no pude encontrar ninguna referencia a ese hecho.

Más que culpar al compilador de mi código, me preguntaba cuál era la razón para que el programa se ejecutara bajo Windows y fallara bajo Linux. Las respuestas re: diferentes administradores de memoria y el diseño de pila / pila en Windows / Linux estaban ilustrando a ese respecto.

¿La conclusión de que el GCC de cygwin es tan bueno como GNU / Linux, y son los sistemas operativos subyacentes / pura suerte que mi buggy program ejecuta bajo uno y no el otro, es más o menos el correcto?

En cuanto a publicar el código fuente, es una tarea para casa, así que preferiría encontrar el problema yo mismo si fuera posible :)

Editar 2

He aceptado la respuesta de jalf, ya que habla de lo que hace que el programa se ejecute en Windows y no en Linux, que era lo que realmente quería saber. Gracias a todos los que contribuyeron, todas fueron respuestas muy interesantes e informativas.

Cuando encuentre el problema y lo solucione, subiré un archivo zip con todo el código fuente de esta versión que no funciona, por si alguien tiene curiosidad por saber qué demonios hice :)

Editar 3

Para aquellos interesados ​​en ver el código, encontré el problema, y ​​de hecho se debió a los indicadores. Intentaba devolver un puntero desde una función. El puntero que estaba tratando de devolver se declaró dentro de la función y, por lo tanto, se destruyó una vez que se ejecutó la función. El código problemático está comentado en las líneas 22-24.

Siéntete libre de ridiculizar mi código.

/** * Returns array of valid searches based on current coordinate */ void determine_searches(int row, int col, int last_row, int last_col, int *active_search){ // define coordinate categories and related valid search directions int Library0[] = {2, 3, 4, -1}; int Library1[] = {4, 5, 6, -1}; int Library2[] = {2, 3, 4, 5, 6, -1}; int Library3[] = {0, 1, 2, 3, 4, 5, 6, 7, -1}; int Library4[] = {0, 1, 2, -1}; int Library5[] = {0, 6, 7, -1}; int Library6[] = {0, 1, 2, 6, 7, -1}; int Library7[] = {0, 1, 2, 3, 4, -1}; int Library8[] = {0, 4, 5, 6, 7, -1}; int * Library[] = { Library0, Library1, Library2, Library3, Library4, Library5, Library6, Library7, Library8, }; // declare (and assign memory to) the array of valid search directions that will be returned //int *active_search; //active_search = (int *) malloc(SEARCH_DIRECTIONS * sizeof(int)); // determine which is the correct array of search directions based on the current coordinate // top left corner int i = 0; if(row == 0 && col == 0){ while(Library[0][i] != -1){ active_search[i] = Library[0][i]; i++; } } // top right corner else if(row == 0 && col == last_col){ while(Library[1][i] != -1){ active_search[i] = Library[1][i]; i++; } } // non-edge columns of first row else if(row == 0 && (col != 0 || col != last_col)){ while(Library[2][i] != -1){ active_search[i] = Library[2][i]; i++; } } // non-edge coordinates (no edge columns nor rows) else if(row != 0 && row != last_row && col != 0 && col != last_col){ while(Library[3][i] != -1){ active_search[i] = Library[3][i]; i++; } } // bottom left corner else if(row == last_row && col == 0){ while(Library[4][i] != -1){ active_search[i] = Library[4][i]; i++; } } // bottom right corner else if(row == last_row && col == last_col){ while(Library[5][i] != -1){ active_search[i] = Library[5][i]; i++; } } // non-edge columns of last row else if(row == last_row && (col != 0 || col != last_col)){ while(Library[6][i] != -1){ active_search[i] = Library[6][i]; i++; } } // non-edge rows of first column else if((row != 0 || row != last_row) && col == 0){ while(Library[7][i] != -1){ active_search[i] = Library[7][i]; i++; } } // non-edge rows of last column else if((row != 0 || row != last_row) && col == last_col){ while(Library[8][i] != -1){ active_search[i] = Library[8][i]; i++; } } active_search[i] = -1; }


Algunos consejos:

  1. Publica tu código Apuesto a que obtendrá una buena contribución que lo hará un mejor programador.

  2. Active las advertencias con la opción -wall y corrija cualquier problema que se informe. Nuevamente, puede ayudarlo a ser un mejor programador.

  3. Paso a paso por el código con un depurador. Además de ayudarte a entender dónde está el problema, te ayudará a convertirte en un mejor programador.

  4. Continúe usando Subversion u otro sistema de control de código fuente.

  5. Nunca culpe al compilador (o sistema operativo o hardware) hasta que esté seguro de haber identificado el problema. Incluso entonces, desconfíe de su propio código.

GCC en Linux es un código fuente idéntico a GCC en Cygwin. Existen diferencias entre las plataformas debido a la capa de emulación Cygwin POSIX y la API subyacente de Windows. Es posible que las capas adicionales sean más indulgentes que el hardware subyacente, pero eso no cuenta.

Ya que es tarea, diría que publicar código es una idea aún mejor. ¿Qué mejor manera de aprender que recibir comentarios de programadores profesionales? Sin embargo, recomendaría acreditar cualquier sugerencia que implemente en comentarios cercanos.


Definitivamente tienes un error en algún lugar de tu código. Es posible que el administrador de memoria de Windows sea más flexible que el administrador de memoria de Linux. En Windows, es posible que esté haciendo cosas malas con la memoria (como sobreescribir límites de matriz, pérdidas de memoria, doble liberación, etc.), pero le permite salirse con la suya. Puede encontrar una historia famosa relacionada con esto en http://www.joelonsoftware.com/articles/APIWar.html (busque "SimCity" en ese artículo (algo extenso)).


Es casi seguro que es un error de puntero o un desbordamiento del búfer, tal vez una variable no inicializada.

Un puntero no inicializado generalmente no apunta a nada, pero a veces apunta a algo; leerlo o escribirlo normalmente bloqueará el programa, pero de nuevo NO PUEDE.

Escribir o leer de la memoria liberada es la misma historia; puedes salirte con la tuya, entonces quizás no.

Estas situaciones dependen exactamente de cómo se distribuyen la pila, el montón y lo que está haciendo el tiempo de ejecución. Es bastante posible hacer un programa malo que funcione en una combinación compilador / tiempo de ejecución y no en otra, simplemente porque en una sobrescribe algo que no importa (mucho), o que una variable no inicializada "pasa" a contener una combinación válida valor para el contexto en el que se usa


La versión de GCC probablemente no sea el problema. Es más probable que haya una diferencia en la biblioteca de tiempo de ejecución y un error en el código que no se manifiesta cuando se ejecuta en la versión de Windows del tiempo de ejecución. Es posible que desee publicar el código que segfaults y más información de fondo si desea una respuesta más específica.

En general, lo mejor es desarrollarse bajo el entorno que va a utilizar para ejecutar su código.


No he oído hablar de nada específico sobre la rareza de GCC bajo Cygwin, pero en su caso, sería una buena idea usar la opción de línea de comandos deWall a gcc para mostrar todas las advertencias, para ver si encuentra algo que pueda estar causando la segfault en tu código.


Una falla de segmentación significa que intentó acceder a la memoria que no pudo, lo que generalmente significa que intentó desreferenciar un puntero nulo o que borró por duplicado la memoria u obtuvo un puntero salvaje. Hay dos razones por las que puede parecer que está bien para cygwin y no para Linux: o bien fue un problema con los administradores de memoria, o usted tuvo más suerte en una de ellas que en la otra. Es casi seguro que es un error con su código.

Para solucionar esto, mira el uso de tu puntero. Considere la posibilidad de sustituir punteros inteligentes por punteros sin procesar. Considere realizar una búsqueda para eliminar y poner a cero el puntero inmediatamente después (es seguro intentar eliminar un puntero nulo). Si puede obtener una grieta en Linux, intente obtener un seguimiento de la pila a través de gdb y vea si hay algo obviamente incorrecto en la línea que sucede. Examine cómo utiliza todos los punteros que no están inicializados. Si tiene acceso a una herramienta de depuración de memoria, úselo.


Como han dicho otros, es posible que desee publicar parte de su código aquí, incluso si ese no es el verdadero objetivo de su pregunta. Todavía puede ser una buena experiencia de aprendizaje que todos accedan a su código y vean si pueden encontrar lo que causó la segfault.

Pero sí, el problema es que hay muchos factores dependientes de la plataforma, así como básicamente aleatorios, que influyen en un programa C. La memoria virtual significa que, a veces , acceder a la memoria no asignada parecerá funcionar, porque se accede a una parte no utilizada de una página asignada en algún momento anterior. Otras veces, segfault porque golpea una página que no ha sido asignada a su proceso en absoluto. Y eso es realmente imposible de predecir. Depende de dónde se asignó su memoria, ¿estaba en el borde de una página o en el medio? Eso depende del sistema operativo y el administrador de memoria, y qué páginas se han asignado hasta el momento, y ...... Ya entendiste la idea. Diferentes compiladores, diferentes versiones de los mismos compiladores, diferentes sistemas operativos, diferentes software, controladores o hardware instalados en el sistema, cualquier cosa puede cambiar si obtienes una segfault cuando accedes a la memoria no asignada.

En cuanto a la afirmación de la AT de que cygwin es más "laxo", eso es basura, por una simple razón. ¡Ninguno de los compiladores detectó el error! Si el compilador GCC "nativo" hubiera sido realmente menos laxo, le habría dado un error en tiempo de compilación. Segfaults no son generados por el compilador. No hay mucho que el compilador pueda hacer para asegurarse de obtener un segfault en lugar de un programa que aparentemente funciona.


La versión de gcc de Cygwin puede tener otros indicadores predeterminados y configuraciones ajustadas (por ejemplo, wchar_t es de 2 bytes), pero dudo que sea específicamente más "laxo" con el código, y aún así, su código no debería fallar. Si lo hace, lo más probable es que haya un error en su código que deba corregirse. Por ejemplo, su código puede depender de un tamaño particular de wchar_t o puede ejecutar código que no se garantiza que funcione en absoluto, como escribir en cadenas literales.

Si escribe código limpio, entonces también se ejecuta en Linux. Actualmente estoy ejecutando Firefox y el escritorio de KDE, que en conjunto constan de millones de líneas C ++, y no veo esas aplicaciones estrellándose :)

Te recomiendo que pegues el código en tu pregunta, para que podamos ver qué está yendo mal.

Mientras tanto, puedes ejecutar tu programa en gdb , que es un depurador para Linux. También puede compilar con todas las comprobaciones de mudplap habilitadas y con todas las advertencias habilitadas. mudflaps verifica su código en tiempo de ejecución por varias violaciones:

[js@HOST2 cpp]$ cat mudf.cpp int main(void) { int a[10]; a[10] = 3; // oops, off by one. return 0; } [js@HOST2 cpp]$ g++ -fmudflap -fstack-protector-all -lmudflap -Wall mudf.cpp [js@HOST2 cpp]$ MUDFLAP_OPTIONS=-help ./a.out ... showing many options ... [js@HOST2 cpp]$ ./a.out ******* mudflap violation 1 (check/write): time=1234225118.232529 ptr=0xbf98af84 size=44 pc=0xb7f6026d location=`mudf.cpp:4:12 (main)'' /usr/lib/libmudflap.so.0(__mf_check+0x3d) [0xb7f6026d] ./a.out(main+0xb9) [0x804892d] /usr/lib/libmudflap.so.0(__wrap_main+0x4f) [0xb7f5fa5f] Nearby object 1: checked region begins 0B into and ends 4B after mudflap object 0x9731f20: name=`mudf.cpp:3:11 (main) int a [10]'' bounds=[0xbf98af84,0xbf98afab] size=40 area=stack check=0r/3w liveness=3 alloc time=1234225118.232519 pc=0xb7f5f9fd number of nearby objects: 1 *** stack smashing detected ***: ./a.out terminated ======= Backtrace: ========= ....

Hay muchas verificaciones de mudflap que puede hacer, y lo anterior se ejecuta a.out usando las opciones predeterminadas. Otra herramienta que ayuda a ese tipo de errores es valgrind , que también puede ayudarlo a encontrar fugas o errores por uno como el anterior. Establecer la variable de entorno "MALLOC_CHECK_" en 1 también imprimirá mensajes por violaciones. Consulte la página de manual de malloc para conocer otros valores posibles para esa variable.

Para verificar dónde se bloquea tu programa, puedes usar gdb :

[js@HOST2 cpp]$ cat test.cpp int main() { int *p = 0; *p = 0; } [js@HOST2 cpp]$ g++ -g3 -Wall test.cpp [js@HOST2 cpp]$ gdb ./a.out ... (gdb) r Starting program: /home/js/cpp/a.out Program received signal SIGSEGV, Segmentation fault. 0x080483df in main () at test.cpp:3 3 *p = 0; (gdb) bt #0 0x080483df in main () at test.cpp:3 (gdb)

Compile su código con -g3 para incluir mucha información de depuración, por lo que gdb puede ayudarlo a encontrar las líneas precisas donde se bloquea su programa. Todas las técnicas anteriores son igualmente aplicables para C y C ++.


No quiero sonar grosero, pero probablemente sea tu código el malo, no el compilador. ;) Los problemas como este son en realidad más comunes de lo que piensas, ya que los diferentes sistemas operativos y compiladores tendrán diferentes formas de organizar los datos de tu aplicación en la pila y en el montón. El primero puede ser particularmente problemático, especialmente si termina sobreescribiendo la memoria en la pila, o haciendo referencia a la memoria liberada que el sistema ha decidido usar para otra cosa. Entonces, básicamente, puede salirse con la suya a veces, pero otras veces su aplicación se ahogará y morirá. De cualquier manera, si segmenta, es porque trataste de hacer referencia a la memoria que no estabas permitida, por lo que es más una "feliz coincidencia" que no se colgó bajo otro sistema / compilador.

Pero en realidad, una segfault es una falla de segmentación, por lo que debería depurar su código buscando corrupción de memoria en lugar de modificar la configuración del compilador para descubrir qué está fallando.

Edit : Ok, veo lo que quieres decir ahora ... Pensé que estabas llegando a este problema con un "X es una mierda, pero Y funciona muy bien". actitud, pero parece ser su TA quien tiene eso. ;)

De todos modos, aquí hay algunos consejos más para la depuración de problemas como este:

  • Busque la aritmética del puntero, referenciando / desreferenciando para posible "doh!" errores Cualquier lugar donde agregue / sustraiga uno (es decir, los errores de fencepost) son particularmente sospechosos.
  • Comente las llamadas a malloc / free alrededor del área problemática y cualquier área asociada donde se utilicen dichos punteros. Si el código deja de bloquearse, entonces te diriges en la dirección correcta.
  • Suponiendo que al menos haya identificado el área general donde se bloquea su código, inserte las declaraciones de retorno anticipadas allí y encuentre el punto donde su código no falla. Esto puede ayudar a encontrar un área en algún lugar entre ese punto y donde su código realmente se cuelga. Recuerde, una segfault como esta no necesariamente ocurre directamente en la línea de código donde está su error.
  • Use las herramientas de depuración de memoria disponibles en su sistema.
    • En Unix, consulte esta guía de depuración de memoria en Unix , y el perfilador valgrind (@Sol, thx para recordarme sobre este)
    • En Visual Studio / Windows, su buen amigo, CrtCheckMemory (), es bastante útil. Además, lea sobre los patrones de depuración de memoria CRT , ya que son una de las características más agradables de trabajar en VS. Muchas veces, simplemente dejando abierta una pestaña de memoria en VS es suficiente para diagnosticar errores como este una vez que memoriza los diversos patrones.
    • En Mac OSX, puede establecer un punto de interrupción en malloc_error_break (ya sea desde gdb o Xcode), lo que hace que el depurador se rompa siempre que malloc detecte daños en la memoria. No estoy seguro de si está disponible en otros sabores de Unix, pero una búsqueda rápida en Google parece indicar que es solo mac. Además, parece existir una versión de valgrind bastante "experimental" para OSX .

Una falla de segmentación es el resultado de acceder a la memoria en una dirección inexistente (o liberada previamente). Lo que me parece muy interesante es que el código NO segfault bajo cygwin. Eso podría significar que su programa usó un puntero salvaje al espacio de direcciones de otros procesos y que realmente fue capaz de leerlo (boquiabierto), o (más probable) el código que realmente causó el segfault no fue alcanzado hasta que el programa se ejecutó bajo Linux .

Recomiendo lo siguiente:

  1. Pegue su código ya que es un problema muy interesante
  2. Envíe una copia de esto a los desarrolladores de cygwin
  3. Obtenga un VPS Linux barato si se le solicitará que produzca más programas que corran bajo Linux, esto hará su vida mucho más fácil.

Una vez que trabaje en Linux (es decir, se desvaneció en su VPS), intente trabajar con los siguientes programas:

  • GDB
  • Valgrind
  • strace

Además, puede probar bibliotecas como la cerca eléctrica para detectar este tipo de cosas a medida que suceden mientras se ejecuta su programa.

Finalmente, asegúrate de que -Wall se pasa a gcc, quieres las advertencias que transmitiría.