x86 CLR силы на 'Любом ЦП' блок.NET

Существенно, да, это безопасно в том смысле, что значение продлится неограниченно долго, потому что это статично.

Это не безопасно в том смысле, что Вы возвратили постоянный указатель на переменные данные, а не переменный указатель на постоянные данные. Лучше, если функциям вызова не позволяют изменить данные:

const char *GetString(void)
{
    static char sTest[5];
    strncpy(sTest, "Test", sizeof(sTest)-1);
    sTest[sizeof(sTest)-1] = '\0';
    return sTest;
}

В простом показанном случае, едва необходимо волноваться о переполнении буфера, хотя моя версия кода действительно волнуется и гарантирует пустое завершение. Альтернатива должна была бы использовать функция TR24731 strcpy_s вместо этого:

const char *GetString(void)
{
    static char sTest[5];
    strcpy_s(sTest, sizeof(sTest), "Test");
    return sTest;
}

, Что еще более важно, оба варианта возвращают (переменный) указатель на постоянные данные, таким образом, пользователь не должен идти, изменяя строку и (вероятно) растаптывая вне диапазона массива. (Как @strager указывает в комментариях, возвращение const char * не является гарантией, что пользователь не попытается изменить возвращенные данные. Однако они должны бросить возвращенный указатель, таким образом, это - неконстанта, и затем измените данные; это вызывает неопределенное поведение, и что-либо возможно в той точке.)

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

[По крайней мере один из других ответов отмечает, что код не повторно используем; это корректно. Версия, возвращая литерал повторно используема. Если повторная входимость важна, интерфейс должен быть зафиксирован так, чтобы вызывающая сторона обеспечила пространство, где данные хранятся.]

56
задан Peter Mortensen 14 February 2013 в 12:04
поделиться

4 ответа

Прошло некоторое время с тех пор, как я пробовал это, но я считаю, что разрядность процесса, вызывающего сборку, определяет, будет ли он JIT-обработан как x86 или x64.

Итак, если вы напишите небольшое консольное приложение и соберите его как x86, а другое как x64, запуск одного или другого приведет к тому, что другие сборки, загруженные в процесс, будут работать как 32- или 64-разрядные. Это, конечно, предполагает, что вы работаете на 64-битной машине.

9
ответ дан 26 November 2019 в 17:27
поделиться

Вы можете узнать, как приложение будет работать, и изменить его статически с помощью приложения CorFlags . Чтобы узнать, как будет работать приложение, используйте:

corflags <PathToExe>

Чтобы изменить способ запуска приложения, используйте:

corflags /32bit+  <PathToExe>

Это заставит EXE-файл работать как 32-битный процесс. Информация о том, как должна работать сборка, хранится в заголовке PE. См. Вопрос о переполнении стека Как определить, скомпилирован ли собственный DLL-файл как x64 или x86? .

Если вы хотите внедрить код во время выполнения, вы должны написать .NET в C ++ / COM. См. Внутреннее устройство .NET: API профилирования и Профилирование (Справочник по неуправляемому API) для получения дополнительных сведений.

Вам нужно будет реализовать обратный вызов JitCompilationStarted и выполнять свою работу там. Если вы пойдете в этом направлении, вам придется создать файл DLL для инъекции как x86, так и x64. Собственные файлы DLL будут загружены CLR после того, как будут установлены следующие переменные среды:

Cor_Enable_Profiling=0x1
COR_PROFILER={CLSID-of-your-native-DLL-file}

Если они установлены правильно, то 64-битная версия «увидит» 64-битные процессы и 32-битная версия "увидит" 32-битные процессы.

60
ответ дан 26 November 2019 в 17:27
поделиться

I'm not sure whether I can help you with this. But this is my experience.

I have a host application,A.exe ( compiled as x86), and I have a client application, B.exe ( compiled as ANY CPU), from the host application. And I launch B.exe from A.exe, using the System.Diagnostic.Process class.

The issue now is if I put the two on a x64 machine, then A.exe will run as x86, whereas the B.exe will run as x64.

But if A.exe calls assembly c ( c.dll, which is compiled as Any CPU), and B.exe also calls c.dll, then c.dll will follow the application that calls it. In other words, in 64 bit machine when A.exe calls it, it will behave like x86 dll, whereas when B.exe calls it, it will behave like x64.

6
ответ дан 26 November 2019 в 17:27
поделиться

Я сделал нечто подобное, создав два (на самом деле три) двоичных файла. У меня было одно определение, был ли процесс, в который я пытался внедрить, 32 или 64-разрядный. Затем этот процесс запустит 32-битную или 64-битную версию вашего двоичного файла инъекции (в отличие от перезапуска, как вы упомянули).

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

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

6
ответ дан 26 November 2019 в 17:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: