yaourt paquetes instalar existe aur arch c++ gcc compilation

c++ - paquetes - GCC: el programa no funciona con la opción de compilación-O3



yaourt (16)

Estoy escribiendo un programa en C ++ que no funciona (obtengo un error de segmentación) cuando lo compilo con optimizaciones (opciones -O1, -O2, -O3, etc.), pero funciona bien cuando lo compilo sin optimizaciones.

¿Hay alguna posibilidad de que el error esté en mi código? o debería asumir que esto es un error en GCC?

Mi versión de GCC es 3.4.6.

¿Hay alguna solución conocida para este tipo de problema?

Hay una gran diferencia de velocidad entre la versión optimizada y la no optimizada de mi programa, así que realmente necesito usar optimizaciones.

Este es mi functor original. El que funciona bien sin niveles de optimizaciones y arroja un error de segmentación con cualquier nivel de optimización:

struct distanceToPointSort{ indexedDocument* point ; distanceToPointSort(indexedDocument* p): point(p) {} bool operator() (indexedDocument* p1,indexedDocument* p2){ return distance(point,p1) < distance(point,p2) ; } } ;

Y este funciona perfectamente con cualquier nivel de optimización:

struct distanceToPointSort{ indexedDocument* point ; distanceToPointSort(indexedDocument* p): point(p) {} bool operator() (indexedDocument* p1,indexedDocument* p2){ float d1=distance(point,p1) ; float d2=distance(point,p2) ; std::cout << "" ; //without this line, I get a segmentation fault anyways return d1 < d2 ; } } ;

Desafortunadamente, este problema es difícil de reproducir porque ocurre con algunos valores específicos. Obtengo la falla de segmentación al clasificar solo uno de entre más de mil vectores, por lo que realmente depende de la combinación específica de valores que tenga cada vector.


Asumiría que tu código está mal primero.
Aunque es difícil de decir.

¿Tu código compila con 0 advertencias?

g++ -Wall -Wextra -pedantic -ansi


Rara vez se trata de la falla del compilador, pero el compilador tiene errores, y a menudo se manifiestan en diferentes niveles de optimización (por ejemplo, si hay un error en un pase de optimización).

En general, al informar problemas de programación: proporcione un ejemplo de código mínimo para demostrar el problema , de forma que las personas puedan simplemente guardar el código en un archivo, compilarlo y ejecutarlo. Haga que reproducir su problema sea lo más fácil posible .

Además, pruebe diferentes versiones de GCC (compilar su propio GCC es muy fácil, especialmente en Linux). Si es posible, intente con otro compilador. Intel C tiene un compilador que es más o menos compatible con GCC (y gratuito para uso no comercial, creo). Esto ayudará a identificar el problema.


Wow, no esperaba respuestas tan rápido, y tantas ...

El error ocurre al ordenar un std :: vector de punteros usando std :: sort ()

Proporciono el functor estricto de orden débil.

Pero sé que el functor que proporciono es correcto porque lo he usado mucho y funciona bien.

Además, el error no puede ser un puntero no válido en el vector porque el error ocurre justo cuando clasifico el vector. Si repito el vector sin aplicar std :: sort primero, el programa funciona bien.

Acabo de usar GDB para tratar de averiguar qué está pasando. El error ocurre cuando std :: sort invoca mi functor. Aparently std :: sort está pasando un puntero no válido a mi functor. (por supuesto, esto sucede solo con la versión optimizada, cualquier nivel de optimización -O, -O2, -O3)


Como experimento, intente ver si esto forzará al compilador a redondear todo de manera consistente.

volatile float d1=distance(point,p1) ; volatile float d2=distance(point,p2) ; return d1 < d2 ;


Como se mostrará la pregunta actualizada;), el problema existe con std::vector<T*> . Un error común con los vectores es reservar () lo que debería haber sido resize () d. Como resultado, estarías escribiendo fuera de los límites de la matriz. Un optimizador puede descartar esas escrituras.


De acuerdo ... Este es uno de los problemas más extraños que he tenido.
No creo que tenga suficientes pruebas para afirmar que es un error de GCC, pero sinceramente ... Realmente parece uno.

Este es mi functor original. El que funciona bien sin niveles de optimizaciones y arroja un error de segmentación con cualquier nivel de optimización:

struct distanceToPointSort{ indexedDocument* point ; distanceToPointSort(indexedDocument* p): point(p) {} bool operator() (indexedDocument* p1,indexedDocument* p2){ return distance(point,p1) < distance(point,p2) ; } } ;

Y este funciona perfectamente con cualquier nivel de optimización:

struct distanceToPointSort{ indexedDocument* point ; distanceToPointSort(indexedDocument* p): point(p) {} bool operator() (indexedDocument* p1,indexedDocument* p2){ float d1=distance(point,p1) ; float d2=distance(point,p2) ; std::cout << "" ; //without this line, I get a segmentation fault anyways return d1 < d2 ; } } ;

Desafortunadamente, este problema es difícil de reproducir porque ocurre con algunos valores específicos. Obtengo la falla de segmentación al clasificar solo uno de entre más de mil vectores, por lo que realmente depende de la combinación específica de valores que tenga cada vector.


El error está en tu código. Es probable que esté haciendo algo que invoca un comportamiento indefinido de acuerdo con el estándar C que simplemente funciona sin optimizaciones, pero cuando GCC hace ciertas suposiciones para realizar sus optimizaciones, el código se rompe cuando esas suposiciones no son verdaderas. Asegúrese de compilar con la opción -Wall , y el -Wextra también podría ser una buena idea, y vea si recibe alguna advertencia. También puede probar -ansi o -pedantic , pero es probable que -pedantic como resultado falsos positivos.


Es casi ( casi ) nunca el compilador.

Primero, asegúrese de estar compilando sin advertencia, con -Wall.

Si eso no le dio un momento "eureka", adjunte un depurador a la versión menos optimizada de su ejecutable que se cuelga y vea qué está haciendo y dónde va.

5 le dará 10 que ha solucionado el problema en este punto.


Es posible que se encuentre con un problema de aliasing (o podría ser un millón de cosas más). Busque la opción -fstrict-aliasing.

Este tipo de pregunta es imposible de responder correctamente sin más información.


Espero obtener algunos votos abajo aquí después de leer algunos de los comentarios, pero en el mundo de la programación de juegos de consola, es bastante conocido que los niveles más altos de optimización a veces pueden generar código incorrecto en casos extremos. Sin embargo, podría ser que los casos límite se puedan arreglar con cambios sutiles en el código.


Me encontré con el mismo problema hace unos días, en mi caso era aliasing. Y GCC lo hace de manera diferente, pero no errónea, en comparación con otros compiladores. GCC se ha convertido en lo que algunos podrían llamar un abogado de reglas del estándar C ++, y su implementación es correcta, pero también tiene que ser realmente correcto en usted C ++, o optimizará algo excesivamente, lo cual es un problema. Pero obtienes velocidad, así que no puedo quejarme.


como otros han señalado, probablemente aliasing estricto. enciéndalo en o3 y vuelva a intentarlo. Supongo que está haciendo algunos trucos de puntero en su functor (tipo de objeto de flotación rápida como int compare? En los 2 bits inferiores) que fallan en las funciones de plantilla en línea. las advertencias no ayudan a atrapar este caso. "si el compilador pudiera detectar todos los problemas de alias estrictos, podría evitarlos", simplemente cambiar una línea de código no relacionada puede hacer que el problema aparezca o desaparezca, ya que cambia la asignación de registros.


Ahora que ha publicado el fragmento de código y se ha encontrado una solución de trabajo (@Windows programmer''s answer), puedo decir que tal vez lo que está buscando es -ffloat-store .

-float-store

No almacene variables de coma flotante en los registros, e inhiba otras opciones que podrían cambiar si se toma un valor de coma flotante de un registro o memoria.

Esta opción evita el exceso de precisión indeseable en máquinas como la 68000 donde los registros flotantes (del 68881) mantienen más precisión de la que se supone que tiene un doble. Del mismo modo para la arquitectura x86. Para la mayoría de los programas, el exceso de precisión solo sirve, pero algunos programas se basan en la definición precisa del punto flotante IEEE. Utilice -ffloat-store para tales programas, después de modificarlos para almacenar todos los cálculos intermedios pertinentes en variables.

Fuente: http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Optimize-Options.html


publica el código en distancia! es probable que haga algo de magia de puntero, ver mi publicación anterior. hacer una tarea intermedia solo oculta el error en tu código al cambiar la asignación de registro. ¡aún más revelador es que la salida cambia las cosas!


Aquí hay un código que parece funcionar, hasta que llegue a -O3 ...

#include <stdio.h> int main() { int i = 0, j = 1, k = 2; printf("%d %d %d/n", *(&j-1), *(&j), *(&j+1)); return 0; }

Sin optimizaciones, obtengo "2 1 0"; con optimizaciones obtengo "40 1 2293680". ¿Por qué? ¡Porque i y k se optimizaron!

Pero estaba tomando la dirección de j y saliendo de la región de memoria asignada a j. Eso no está permitido por el estándar. Es muy probable que su problema sea causado por una desviación similar del estándar.

Encuentro valgrind a menudo es útil en momentos como estos.

EDITAR: Algunos comentaristas tienen la impresión de que el estándar permite una aritmética de puntero arbitraria. No es asi. Recuerde que algunas arquitecturas tienen esquemas de direccionamiento divertidos, la alineación puede ser importante y puede tener problemas si desborda ciertos registros.

Las palabras del estándar [borrador], al agregar / restar un entero a / desde un puntero (énfasis agregado):

"Si tanto el operando del puntero como el resultado apuntan a elementos del mismo objeto de la matriz, o uno más allá del último elemento del objeto de la matriz, la evaluación no producirá un desbordamiento, de lo contrario, el comportamiento no está definido " .

Al ver como & j ni siquiera apunta a un objeto de matriz, & j-1 y & j + 1 difícilmente pueden apuntar a una parte del mismo objeto de matriz. Así que simplemente evaluar & j + 1 (y mucho menos desreferenciarlo) es un comportamiento indefinido.

En x86 podemos estar bastante seguros de que agregar uno a un puntero es bastante seguro y solo nos lleva a la siguiente ubicación de memoria. En el código anterior, el problema ocurre cuando hacemos suposiciones sobre qué contiene esa memoria, que por supuesto el estándar no se acerca.


La respuesta verdadera está escondida en algún lugar dentro de todos los comentarios en este hilo. Primero que nada: no es un error en el compilador.

El problema tiene que ver con la precisión de coma flotante. distanceToPointSort debe ser una función que nunca debe volverse verdadera para los argumentos (a, b) y (b, a), pero eso es exactamente lo que puede suceder cuando el compilador decide usar una mayor precisión para algunas rutas de datos. El problema es especialmente probable, pero no limitado a, x86 sin -mfpmath=sse . Si el comparador se comporta de esa manera, la función de sort puede confundirse y la falla de segmentación no es sorprendente.

Considero -ffloat-store la mejor solución aquí (ya sugerida por CesarB).