В SDK есть утилита PDBCopy, которая вырезает большую часть информации, оставляя, грубо говоря, только имена функций и глобальных переменных. Почти все файлы символов с публичного сервера MS пропущены через неё. Важные исключения — ntoskrnl.pdb (и варианты вроде ntkrnlmp.pdb) и ntdll.pdb, там структуры есть.
Это уже следующий этап: компиляторы не умеют генерировать условную LODSB -> условная LODSB в программах встречается редко -> при разработке следующих моделей процессора оптимизируют те инструкции, которые встречаются чаще -> условная LODSB становится медленнее пары MOV/INC.
Да, для main специальное исключение в 3.6.1 [basic.start.main] «If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;» и в C++ тоже.
Это UB в C++ (6.6.3 [stmt.return] «Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.»), где возвращаемое значение может иметь разные интересные штуки вроде деструктора, оператора присваивания и быть подвержено RVO, но не в Си.
Но вот то что cl.exe внезапно оказался not valid Win32 image — это был удар.
Для справки. В PE-заголовке есть поле «версия подсистемы», системный загрузчик в принципе отказывается загружать exe-шники, у которых это поле больше версии системы, именно с ошибкой «not valid Win32 image». Лечится editbin /subsystem:console,5.0 cl.exe (warning LNK4241 можно игнорировать). 2012-й студии под рукой нет, cl.exe из 2013-й студии после такой операции не работает уже по другой, более ясной причине «Точка входа в процедуру InitializeCriticalSectionEx не найдена в библиотеке DLL KERNEL32.dll.» — и действительно, такая API-функция появилась только в Vista.
Под Win9x и Wine таки запускается. Но вы всё равно обрабатываете такую ситуацию неправильно, потому что в Win9x и Wine содержимое на пересечении секций разное, а у вас нет настроек, указывающих, с каким именно загрузчиком вы пытаетесь быть совместимы. Если вы выбираете первую подходящую секцию (как Win9x), то у вас расхождение с Wine. Если последнюю подходящую (как Wine) — то расхождение с Win9x.
При аппаратной виртуализации CPUID прекрасно перехватывается, что у Intel (безусловно)
The following instructions cause VM exits when they are executed in VMX non-root
operation: CPUID, GETSEC, INVD, and XSETBV. This is also true of instructions
introduced with VMX, which include: INVEPT, INVVPID, VMCALL, VMCLEAR,
VMLAUNCH, VMPTRLD, VMPTRST, VMREAD, VMRESUME, VMWRITE, VMXOFF, and
VMXON.
что у AMD (условно, перехват включается одним из бит в VMCB control area).
Это нетрудно проверить. Вот два файла (MessageBox-ные HelloWorld), в которых испорчен VirtualSize первой секции так, чтобы заползал на вторую: 32-bit, 64-bit. Если где-нибудь запустится — расскажите. Работать может разве что под 9x (это не факт — не знаю, не проверял и не ковырял), но, кажется, в 2014 году про неё можно уже не вспоминать.
1. k есть в формулировке задачи. Если формулировку дополнить словами «давайте рассматривать поведение при фиксированном k», то корректно. Если пытаться выяснить зависимость от k тоже, то формально все равенства из моего комментария остаются верными, но асимптотические становятся бесполезными из-за того, что неявные константы внутри O() зависят от k.
2. Верхняя оценка есть в моём комментарии выше. Нижняя оценка: C_m^0+...+C_m^k \le 1+...+m^k/k! \le (m+k)^k/k! (можно раскрыть по формуле бинома и сравнить коэффициенты при степенях m), откуда m_0 \ge (k!n)^(1/k)-k.
При фиксированном k и растущем n, или, хотя бы, если k растёт медленнее логарифма n, эта оценка заведомо точнее, чем изложенный в посте подход: оценка Чернова даёт правильный порядок, только если k по порядку сравнимо с m (что примерно соответствует тому, что k растёт пропорционально логарифму n). Если же m существенно больше k, то сумма биномиальных коэффициентов определяется несколькими наибольшими, и оценки из комментариев точные по порядку.
Кстати, ещё чуть более точное «попадание» в случае, когда k растёт медленнее логарифма, можно получить, если включить второй член асимптотики после m^k: вместо m^k/k! точнее будет приближение C_m^k = m(m-1)...(m-k+1)/k! = (m^k — (1+...+(k-1))m^(k-1) + O_k(m^(k-2)))/k! = (m^k — m^(k-1)k(k-1)/2)/k! + O_k(m^(k-2)), C_m^(k-1) = m^(k-1)/(k-1)! + O_k(m^(k-2)), остальные члены суммы попадают в остаточный член, окончательно (m^k — m^(k-1)k(k-3)/2)/k! + O_k(m^(k-2)) = (m — (k-3)/2)^k/k! + O_k(m^(k-2)), откуда m_0 \approx (k!n)^(1/k) + (k-3)/2.
Если k фиксировано, а m растёт, то в сумме биномиальных коэффициентов Cm0+...+Cmk почти весь вклад даёт последний член, потому что он растёт как (mk/k!)(1+O(1/m)), все остальные — как меньшие степени m, так что Cm0+...+Cmk=(mk/k!)(1+O(1/m)) и при фиксированном k асимптотически m0=(k!n)1/k+O(1). Например, для упомянутых в статье n=400, k=4 выражение (k!n)1/k равно 9.898… Если хочется именно оценок, а не асимптотики: например, Cm0+...+Cmk>Cmk>(m-k+1)k/k!, откуда m0≤(k!n)1/k+(k-1) (можно вычесть единицу из n за счёт Cm0 в сумме, но это уже незначимые мелочи).
Числа 4680, 600, 270 появляются следующим образом. Доказывают утверждение в такой формулировке: если k достаточно большое, то для любого набора h1, ..., hk из k чисел, удовлетворяющего свойству А (admissible set), существует бесконечно много чисел n таких, что хотя бы два из чисел n+h1, ..., n+hk простые. Если доказать такое утверждение, остаётся только предъявить один конкретный набор со свойством А, тогда получится граница (максимальное число набора) — (минимальное число набора).
Для гипотезы простых-близнецов достаточно доказать формулировку с k=2; тогда можно взять набор из двух чисел 0 и 2. Но получается доказать только с большими значениями k. Результат с k=632 соответствует границе 4680, вот набор из 632 чисел от 0 до 4680, удовлетворяющий свойству A: http://math.mit.edu/~primegaps/tuples/admissible_632_4680.txt. Граница 600 соответствует k=105, граница 270 — k=54. Вообще, вот ссылка, взятая из черновика polymath8a: http://math.mit.edu/~primegaps/.
Свойство А набора означает, что для каждого простого числа p множество различных остатков набора по модулю p не содержит хотя бы одного из возможных. На примере http://math.mit.edu/~primegaps/tuples/admissible_54_270.txt для границы 270:
модуль 2: все числа набора чётные, нет остатка 1;
модуль 3: каждое из чисел набора имеет вид либо 3m, либо 3m+1, нет остатка 2;
модуль 5: последняя цифра каждого числа набора — одна из 0, 2, 4, 8, нет остатка 1 (он же 6);
и так для бесконечного количества простых.
(Конечно, начиная с 59, условие выполнено автоматически, потому что всего различных остатков не более 54.)
Уже предвижу следующий вопрос: откуда берутся значения k? А вот тут начинается хардкор. Например, для черновика polymath8a финальное значение получается оптимизацией k (там оно называется k0) в рамках ограничений следующих двух теорем:
use modulename;
.что у AMD (условно, перехват включается одним из бит в VMCB control area).
2. Верхняя оценка есть в моём комментарии выше. Нижняя оценка: C_m^0+...+C_m^k \le 1+...+m^k/k! \le (m+k)^k/k! (можно раскрыть по формуле бинома и сравнить коэффициенты при степенях m), откуда m_0 \ge (k!n)^(1/k)-k.
При фиксированном k и растущем n, или, хотя бы, если k растёт медленнее логарифма n, эта оценка заведомо точнее, чем изложенный в посте подход: оценка Чернова даёт правильный порядок, только если k по порядку сравнимо с m (что примерно соответствует тому, что k растёт пропорционально логарифму n). Если же m существенно больше k, то сумма биномиальных коэффициентов определяется несколькими наибольшими, и оценки из комментариев точные по порядку.
Кстати, ещё чуть более точное «попадание» в случае, когда k растёт медленнее логарифма, можно получить, если включить второй член асимптотики после m^k: вместо m^k/k! точнее будет приближение C_m^k = m(m-1)...(m-k+1)/k! = (m^k — (1+...+(k-1))m^(k-1) + O_k(m^(k-2)))/k! = (m^k — m^(k-1)k(k-1)/2)/k! + O_k(m^(k-2)), C_m^(k-1) = m^(k-1)/(k-1)! + O_k(m^(k-2)), остальные члены суммы попадают в остаточный член, окончательно (m^k — m^(k-1)k(k-3)/2)/k! + O_k(m^(k-2)) = (m — (k-3)/2)^k/k! + O_k(m^(k-2)), откуда m_0 \approx (k!n)^(1/k) + (k-3)/2.
Для гипотезы простых-близнецов достаточно доказать формулировку с k=2; тогда можно взять набор из двух чисел 0 и 2. Но получается доказать только с большими значениями k. Результат с k=632 соответствует границе 4680, вот набор из 632 чисел от 0 до 4680, удовлетворяющий свойству A: http://math.mit.edu/~primegaps/tuples/admissible_632_4680.txt. Граница 600 соответствует k=105, граница 270 — k=54. Вообще, вот ссылка, взятая из черновика polymath8a: http://math.mit.edu/~primegaps/.
Свойство А набора означает, что для каждого простого числа p множество различных остатков набора по модулю p не содержит хотя бы одного из возможных. На примере http://math.mit.edu/~primegaps/tuples/admissible_54_270.txt для границы 270:
Уже предвижу следующий вопрос: откуда берутся значения k? А вот тут начинается хардкор. Например, для черновика polymath8a финальное значение получается оптимизацией k (там оно называется k0) в рамках ограничений следующих двух теорем:
… за поддержку USB- и Bluetooth-клавиатур — бонусные баллы…