Строковый литерал, такой как "\xB8\x0C\x00\x00\x00\xC3"
, является объектом статической длительности хранения [lex.string] / 15 . Компилятор обычно помещает такие строковые литеральные объекты в секцию .rdata
вашего двоичного файла, то есть в неисполняемую память только для чтения. Как следствие, попытка выполнить байты строкового литерала приведет к нарушению доступа. Если вы хотите выполнить байты машинного кода, содержащиеся в объекте глобального массива, вы должны убедиться, что ваш объект размещен в исполняемом разделе. Например (для Windows с Visual C ++):
#include <iostream>
#pragma section("runstuff", read, execute)
__declspec(allocate("runstuff"))
const unsigned char code[] = {
0xB8, 0x0C, 0x0, 0x0, 0x0, 0xC3
};
int main()
{
auto fun_ptr = reinterpret_cast<int(*)()>(&code[0]);
std::cout << fun_ptr();
return 0;
}
Обратите внимание, что подобные вещи по своей природе не переносимы и в лучшем случае имеют поведение, определяемое реализацией. Если вы знаете во время сборки, какой машинный код вы хотите запустить, рассмотрите возможность использования ассемблера и просто связывания получившегося объектного файла с вашим исполняемым файлом. Если вы хотите динамически генерировать машинный код в Windows, вам придется выделить исполняемую память. Для этого либо создайте достаточно большой массив в исполняемой (и также записываемой) памяти (например, аналогично моему примеру выше), в который вы можете поместить свой код, или динамически распределить исполняемую память, например, используя VirtualAlloc
или HeapAlloc
из кучи с установленным флагом исполняемого файла . Вам также понадобится знать о FlushInstructionCache
API & hellip;