Допустим ли стандарт C для самоизменяющегося кода? - PullRequest
5 голосов
/ 19 июня 2011

Возможен ли самоизменяющийся код переносимым способом в C?

Причина, по которой я спрашиваю, заключается в том, что ООП в некотором смысле полагается на самоизменяющийся код (потому что код, который выполняется во время выполнения, фактически генерируется как данные, например, в v-таблице), и, тем не менее, кажется, что если это зайти слишком далеко, это предотвратит большинство оптимизаций в компиляторе.

Например:

void add(char *restrict p, char *restrict pAddend, int len)
{
    for (int i = 0; i < len; i++)
        p[i] += *pAddend;
}

Оптимизирующий компилятор может вывести *pAddend из цикла, потому что это не помешает p. Однако это больше не является действительной оптимизацией в самомодифицирующемся коде .

Таким образом, кажется, что C не допускает самоизменяющегося кода, но в то же время, не означает ли это, что вы не можете делать такие вещи, как ООП в C? Действительно ли C поддерживает самоизменяющийся код?

Ответы [ 2 ]

8 голосов
/ 19 июня 2011

Самоизменяющийся код невозможен в C по многим причинам, наиболее важными из которых являются:

  1. Код, сгенерированный компилятором, полностью зависит от компилятора и может не выглядеть так, как ожидает программист, пытающийся написать код, который модифицирует сам себя. Это фундаментальная проблема с SMC, а не просто проблема переносимости.
  2. Указатели функций и данных полностью разделены в C; язык не дает возможности конвертировать между ними. Эта проблема не является фундаментальной, поскольку некоторые реализации или стандарты более высокого уровня (POSIX) гарантируют, что код и указатели данных совместно используют представление.

Кроме того, самоизменяющийся код - это действительно очень плохая идея. 20 лет назад он мог иметь некоторые применения, но в настоящее время это приведет только к ошибкам, ужасной производительности и сбоям в переносимости. Обратите внимание, что на некоторых ISA даже то, видит ли кеш команд изменения, внесенные в кешированный код, может быть неопределенным / непредсказуемым!

Наконец, vtables не имеет ничего общего с самоизменяющимся кодом. Это просто вопрос модификации функции указатели , которые являются данными, а не кодом.

3 голосов
/ 19 июня 2011

Строго говоря, самоизменяющийся код не может быть реализован переносимым способом на C или C ++, если я правильно понял стандарт.

Самомодифицирующийся код в C / C ++ будет означать что-то вроде этого:

uint8_t code_buffer[FUNCTION_SIZE];
void call_function(void)
{
   ... modify code_buffer here to the machine code we'd like to run.
   ((void (*)(void))code_buffer)();
}

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

У большинства современных ОС есть возможность сделать этот хакер, который используется динамическими перекомпиляторами для одного. Например, mprotect () в Unix.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...