Умный способ сделать одну и ту же сборку выполненной по-разному? - PullRequest
1 голос
/ 31 июля 2009

Не изменяя процесс сборки или включая исходные файлы, кто-нибудь может придумать способ сделать два куска кода, которые при компиляции генерируют одну и ту же сборку, но при этом выполняются по-разному? Я уже знаю, почему это должно быть невозможным, поэтому, пожалуйста, не пытайтесь объяснить. Определенно есть способы сделать это, прежде всего, путем поиска способов скрыть информацию в исходном коде, которая заканчивается где-то, кроме исполняемого.

Довольно скучный и необработанный пример, который может сделать это: создать кусок кода, который занимает много времени для анализа, но оптимизируется во время процесса компиляции (или просто добавляет столько пробелов, что дисковый ввод-вывод замедляет компиляцию ). Сделайте так, чтобы ваша программа генерировала как exe, так и dll в процессе сборки. Пусть программа ведет себя по-разному в зависимости от разницы между созданными временными метками на dll и exe. Это довольно неудачный пример. Интересно, может кто-нибудь придумать что-нибудь более умное.

Можно также как-то сгенерировать другой вывод для отладки, и это изменило бы, как работает код, но это тоже немного неубедительно.

Это, конечно, более впечатляюще, если ваш код, похоже, не проверяет себя или вывод. Если кто-то, глядя на ваш код, будет шокирован тем, что две версии ведут себя по-разному, это отличный ответ.

Ответы [ 6 ]

4 голосов
/ 31 июля 2009

Там также Самоизменяющийся код

[S] elf-модифицирующий код - это код, который изменяет свои собственные инструкции во время выполнения

Таким образом, теоретически, вы можете использовать некоторый код для просмотра временной метки и заставить код сам изменяться на основе этого. У SO есть статья: Какая польза от самоизменяющегося кода?

3 голосов
/ 31 июля 2009

Вот общий пример использования Python в качестве псевдокода:

input = raw_input("type something!\n")
if "a" in input:
    print "Great job!"
else:
    print "Ohh, too bad."

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

Объяснение: если сборка двух исполняемых файлов абсолютно одинакова, то выполнение будет точно таким же. Поведение может отличаться, но это полностью зависит от входных данных, которые каждый получает при запуске. Задание времени ввода исполняемого файла допустимо, но по сути бесполезно.

1 голос
/ 04 сентября 2009

Ну, это никогда не может быть «выполнено» по-другому. Он всегда выполняется только тем способом, который вы описываете (как бы не было понятно, он все еще следует правилам выполнения для данной среды).

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

Это невозможно, и на то есть веская причина: компьютеры логичны, и даже если вы запрограммируете их так, чтобы они вели себя по-разному в другой среде, они все равно следовали изложенным вами правилам. И слава Богу, потому что, если бы компьютер мог решать, исходя из своих собственных чувств, мы, программисты, столкнемся с некоторыми проблемами ...

int k = 2;

// computer internally has decided k should = 5, because it is upset about a prior 
// argument, so you must actually write:

computer.pleaseWork();
int k = 2;
1 голос
/ 04 сентября 2009

Если это один и тот же битовый шаблон в памяти, и программа выполняется в том же начальном состоянии, детерминизм отдельных команд вызовет детерминистический ответ. (В противном случае вы ничего не сможете отладить).

Теперь, у вас могут быть инструкции, которые дают разные результаты в зависимости от внешнего состояния («недавно процессор попал в космический луч?»). Это даст разные результаты. Одной конкретной инструкцией, которая производит этот эффект на x86, является RDTSC, «счетчик меток времени чтения», который считывает количество тактов для текущего ЦП с момента запуска выполнения. Если операционная система прерывает ваше приложение и не сохраняет / восстанавливает содержимое RDTSC, то разные исполнения будут видеть разные значения RDTSC в одной и той же точке кода («недавно произошел сбой космического прерывания ЦП»).

Реальная проблема в том, что результат не контролируется программой, поэтому трудно гарантировать, что программа ведет себя по-разному контролируемым образом.

Что вы пытаетесь достичь с этим?

1 голос
/ 31 июля 2009

Если вы работали над этим достаточно усердно, у вас должна быть возможность иметь точно такой же кусок машинных инструкций для выполнения двух разных вещей, если перейти к «середине» одной из исходных инструкций, и в этом случае процессор увидит совершенно другая последовательность инструкций. IIRC, высоко оптимизированный под космический код в ПЗУ для 8-битных компьютеров в начале 80-х, сделал это совсем немного для экономии места.

1 голос
/ 31 июля 2009

Посмотрим, пойму ли я. Предположим, вы заявляете, что можете это сделать. Вы пишете две разные программы, которые приводят к одинаковым сборкам. Вы кладете каждый на CD-ROM. Компакт-диски идентичны по битам. Вы помечаете их A и B ручкой. Я положил один или другой в свой компьютер и установить его. Если я установил диск с надписью «A», программа отобразит «Я программа A.» Если я установил диск с надписью «B», программа отобразит «Я - программа B».

Я не вижу, как это возможно.

Есть, конечно, трюки, которые вы можете сделать. Если вы видите, какой диск я вставил, вы можете тайно нажать A или B на своем мобильном телефоне, отправив сообщение на ваш веб-сервер, которое получено программой.

...