2010-08-31 16 views
8

Mi programa supuestamente determinista produce una de las pocas salidas ligeramente diferentes en diferentes ejecuciones. La entrada, el compilador y la computadora no cambian. No estoy seguro de qué salida es correcta porque siempre parece razonable.Fuentes de no determinismo

Además de una llamada perdida a rand(), ¿cómo podría ser esto posible?

+7

Habría que ver algo de código antes de hacer especulaciones. –

+2

¿Su código contiene algo que se desvía hacia la tierra del comportamiento indefinido? –

+1

¿Quién dijo que los compiladores son deterministas? – AshleysBrain

Respuesta

16

de varias maneras:

  • utilizando múltiples hilos de una manera que implica un data race,
  • usin g la hora del sistema actual como entrada,
  • usando variables sin inicializar,
  • ...

seguramente Podemos hacer más conjeturas, pero si usted desea conseguir una ayuda significativa, tal vez sería bueno para usted para publicar las partes relevantes de su código :-)

+0

Sí; necesitamos código! Por supuesto, todos estos factores, así como los errores decimales y las pseudoaleatorizaciones son técnicamente deterministas ya que se ejecutan en una máquina determinista. Simplemente no nos parecen deterministas cuando no podemos rastrear o comprender las entradas y los millones de estados progresivos de nuestro programa en el contexto de un sistema de tiempo compartido controlado menos personalmente. Es por eso que la teoría y la informática siempre son importantes para enseñar junto con las habilidades de programación de tuercas y tornillos. –

+0

Debería haber dejado en claro que solo quería una lista de posibilidades comunes, que es lo que obtuve. Gracias. – zoo

7

Podría ser:

  • tiempo de rosca
  • Cualquier tipo de entrada (usuario, archivos, red, etc.)
3

Sin ver ningún código (CONSEJO CONSEJO), lo mejor que puedo pensar sería buscar un patrón. Tal vez algo específico de la fecha y hora.

Además, intente buscar condiciones de carrera. Eso puede parecer no determinista.

7

Si su salida depende de una dirección asignada en el montón:

int main(int argc, char* argv[]) 
{ 
    printf("%p", malloc(42)); 
    return 0; 
} 

Para cada ejecución, el malloc() puede devolver una dirección diferente virtuales - por no hablar de NULL en caso de que la asignación falló.

+2

Buena captura. La aleatorización de direcciones de pila/pila es una característica bastante estándar hoy en día. Eso tendría un efecto si los punteros se utilizan como claves en alguna parte. Lo usé en un par de ocasiones para hacer que el género sea estable (si las claves son iguales, compara los punteros). – Dummy00001

+0

Sin embargo, tendrías que ser bastante desafortunado/ejecutar con muy poca memoria para tener una falla de asignación. – zneak

+0

La salida dependería de una dirección asignada en el montón si los objetos asignados en el montón se ordenan por su dirección, por ejemplo, si los punteros se almacenan en un contenedor ordenado como un conjunto. – Richard

2

Usar el valor de un puntero en lugar de lo que apunta a siempre produce resultados interesantes.

5

Además de una llamada perdida a rand()

rand() es completamente determinista, siempre y cuando le da de comer la misma semilla inicial.

0
  • Entradas desde la red/Internet.
  • fecha/hora
1

En los programas que no interactúan mucho con el "mundo exterior", la fuente popular de no determinismo es la confianza en comparación puntero. De vez en cuando puede verlo en el código: cuando una función de comparación lexicográfica se queda sin cosas para comparar (todo es igual), compara las direcciones de objetos como último recurso. Esto puede producir diferentes ordenamientos si los objetos están asignados en la memoria dinámica, ya que las ubicaciones de asignación reales pueden diferir de una plataforma a otra y de una ejecución a otra.

0

No proporcionó mucha información. Sin embargo, como alguien que hace programación en tiempo real para ganarse la vida, los culpables más probables que busco cuando suceden tales cosas es:

  • Uso de memoria no inicializada.
  • Una condición de carrera.
  • Alguna combinación oscura de las anteriores.

Por ejemplo, uno de esos problemas que tuve una vez fue que la biblioteca compartida no era tan "compartida" como pensé, y tratando de usar un identificador de un proceso para indexar una tabla que aún no se inicializaba en una segundo proceso. Dependiendo de cómo empezaron las cosas, es posible que haya o no haya causado datos importantes en un tercer proceso que se haya destruido.

0

Cualquier comportamiento indefinido. es decir: llevará cientos de páginas explicar cada posible fuente de alteración de la salida. Intente depurar para encontrar donde ocurre la alteración, o leyendo algunas especificaciones de C++.

3

Si su programa usa float/double, puede haber una diferencia en el resultado si hay un cambio de contexto en alguna arquitectura.

En x86, la FPU usa una precisión extendida para el resultado intermedio, pero cuando se guarda en la memoria (lo que sucede cuando hay un cambio de contexto en proceso o subproceso), dicha precisión se pierde. Eso podría causar una pequeña divergencia del resultado (hemos detectado tal problema en nuestro programa). Una forma de evitar este problema es pedirle al compilador que no use FPU sino SSE para operaciones de coma flotante.

http://www.network-theory.co.uk/docs/gccintro/gccintro_70.html