2010-08-31 5 views
8

Моя предположительно детерминированная программа производит один из нескольких немного разных выходов на разных прогонах. Вход, компилятор и компьютер неизменны. Я не уверен, какой вывод прав, потому что он всегда выглядит разумным.Источники недетерминированности

Помимо бродячего звонка на rand(), как это возможно?

+7

Мы должны видеть некоторый код, прежде чем сделать дикие домыслы. –

+2

В вашем коде содержится что-то, что попадает в землю неопределенного поведения? –

+1

Кто сказал, что компиляторы детерминированы? – AshleysBrain

ответ

16

несколькими способами:

  • использованием множественного нити таким образом, который включает в себя: data race,
  • usin г текущее системное время в качестве входных данных,
  • с использованием неинициализированных переменных,
  • ...

Мы можем, конечно, сделать больше догадок, но если вы хотите, чтобы получить значимую помощь, может быть, это было бы хорошо для вас опубликовать соответствующие части вашего кода :-)

+0

Да; нам нужен код! Конечно, все эти факторы, а также десятичные ошибки и псевдо-рандомизации являются технически детерминированными, поскольку они работают на детерминированной машине. Они просто кажутся нам недетерминированными, когда мы не можем отслеживать или понимать вклад и миллионы прогрессивных состояний нашей программы на фоне менее лично контролируемой системы разделения времени. Его почему теория и информатика всегда важны для обучения наряду с навыками программирования орехов и болтов. –

+0

Я должен был четко указать, что мне нужен только список общих возможностей, что я и получил. Благодарю. – zoo

7

Это может быть:

  • времени резьбы
  • Любой вид входа (пользователь, файл, сеть и т.д.)
3

Не видя какого-либо кода (СОВЕТ), лучшее, что я могу придумать, будет искать шаблон. Возможно, что-то конкретное время.

Кроме того, попробуйте найти условия гонки. Это может выглядеть недетерминированным.

7

Если выход зависит от адреса, выделенного в куче:

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

Для каждого прогона, в таНосе() может возвращать другой виртуальный адрес - не говоря уже о NULL в случае, если распределение не удалось.

+2

Хороший улов. В настоящее время рандомизация адресного списка кучи/стека является довольно стандартной функцией. Это может повлиять на то, что указатели используются как ключи где-то. Я использовал это несколько раз, чтобы сделать сортировку стабильной (если ключи равны, сравните указатели). – Dummy00001

+0

Хотя вам будет очень не повезло/работать в очень низкой памяти, чтобы иметь отказ в распределении. – zneak

+0

Выход будет зависеть от адреса, выделенного в куче, если выделенные объекты кучи сортируются по их адресу, например, если указатели на них хранятся в упорядоченном контейнере, таком как набор. – Richard

2

Использование значения указателя вместо того, что указывает на всегда, дает интересные результаты.

5

Кроме шальной вызова рандов()

rand() полностью детерминированным, пока вы кормите его же начальное семя.

1

В программах, которые не взаимодействуют много с «внешним миром» популярным источником индетерминизма является опора на сравнение указателя. Время от времени вы можете увидеть это в коде: когда функция лексикографического сравнения исходит из вещей для сравнения (все равно), она сравнивает адреса объектов в крайнем случае. Это может привести к различным упорядочениям, если объекты распределены в динамической памяти, поскольку фактические местоположения размещения могут отличаться от платформы к платформе и от запуска до запуска.

0

Вы не дали много информации. Однако, как и кто-то, кто занимается программированием в реальном времени для жизни, наиболее вероятными виновниками я ищу, когда такие вещи происходят:

  • Использование неинициализированной памяти.
  • A гонки состояние.
  • Некоторые неясные комбинации выше.

Например, одна такая проблема, с которой я когда-то попал в разделяемую библиотеку, не будучи «разделенной», как я думал, и пытаюсь использовать дескриптор из одного процесса для индексации таблицы, которая еще не была инициализирована в второй процесс. В зависимости от того, как все началось, что может или не могло привести к тому, что важные данные еще в третьем процессе будут обработаны.

0

Любое неопределенное поведение. то есть на сотни страниц будут объясняться все возможные источники изменения выходных данных. Попробуйте отладить, чтобы найти , где происходит изменение, или чтение некоторых спецификаций C++.

3

Если ваша программа использует float/double, может быть разница в результате, если на какой-либо архитектуре есть контекстный переключатель.

На x86 FPU использует расширенную точность для промежуточного результата, но при сохранении в памяти (что происходит при переключении контекста либо в процессе, либо в потоке) такая точность теряется. Это может привести к небольшому расхождению результата (мы обнаружили такую ​​проблему в нашей программе). Один из способов избежать этой проблемы - попросить компилятор не использовать FPU, кроме SSE для операций с плавающей запятой.

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