Исключение нарушения прав доступа EnterCriticalSection WinAPI C#

Я не понимаю, что вызывает эту ошибку

[DllImport("kernel32.dll")]
static extern void EnterCriticalSection(ref IntPtr lpCriticalSection);

[DllImport("kernel32.dll")]
static extern void LeaveCriticalSection(ref IntPtr lpCriticalSection);

public Form1()
{
   InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
    unsafe
    {
        try
        {
            IntPtr criticalSection = new IntPtr();
            EnterCriticalSection(ref criticalSection);
            LeaveCriticalSection(ref criticalSection);
        }
        catch (AccessViolationException exception)
        {
            Console.WriteLine(exception.Message);
        }
    }
}

Пробовал в Visual Studio изменить тип сборки с Any CPU на x86, но результатов это не принесло.

Во-первых, вы должны удалить refs. Во-вторых, вы не можете войти в критическую секцию, которая не была инициализирована. В-третьих, вам не нужно использовать критические секции в C#.

GSerg 18.06.2023 19:54

Вам действительно нужна низкоуровневая критическая секция? C# имеет встроенные функции синхронизации, такие как lock.

Serg 18.06.2023 19:58

прочитать инструкцию learn.microsoft.com/en-us/windows/win32/api/synchapi/…

pm100 18.06.2023 20:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

EnterCriticalSection() ожидает получить указатель на структуру CRITICAL_SECTION, которая была инициализирована с помощью InitializeCriticalSection() или InitializeCriticalSectionAndSpinCount().

Но вместо этого вы даете ему ссылку на неинициализированный IntPtr, который не указывает ни на что значимое. Отсюда и сбой, когда EnterCriticalSection() пытается получить доступ к несуществующей структуре.

Правильный код должен выглядеть примерно так:

[StructLayout(LayoutKind.Sequential)]
public struct CRITICAL_SECTION
{
    public IntPtr DebugInfo;
    public int LockCount;
    public int RecursionCount;
    public IntPtr OwningThread;
    public IntPtr LockSemaphore;
    public UIntPtr SpinCount;
}

[DllImport("kernel32.dll")]
static extern void InitializeCriticalSection(ref CRITICAL_SECTION lpCriticalSection);

[DllImport("kernel32.dll")]
static extern void DeleteCriticalSection(ref CRITICAL_SECTION lpCriticalSection);

[DllImport("kernel32.dll")]
static extern void EnterCriticalSection(ref CRITICAL_SECTION lpCriticalSection);

[DllImport("kernel32.dll")]
static extern void LeaveCriticalSection(ref CRITICAL_SECTION lpCriticalSection);

public Form1()
{
   InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
    unsafe
    {
        try
        {
            CRITICAL_SECTION criticalSection = new CRITICAL_SECTION();
            InitializeCriticalSection(ref criticalSection);
            EnterCriticalSection(ref criticalSection);
            LeaveCriticalSection(ref criticalSection);
            DeleteCriticalSection(ref criticalSection);
        }
        catch (AccessViolationException exception)
        {
            Console.WriteLine(exception.Message);
        }
    }
}

Однако вам действительно не нужно использовать CRITICAL_SECTION в C#, вместо этого используйте оператор блокировки или примитив синхронизации , например System.Threading.Monitor.

Будет ли это работать вообще, если GC решит переместить структуру между вызовами? т.е. stackoverflow.com/a/3269274/11683.

GSerg 19.06.2023 00:12

struct — это тип значения, его нельзя перемещать, только копировать (но в документах CRITICAL_SECTION говорится, что его нельзя копировать или перемещать). CRITICAL_SECTION содержит в качестве членов только другие типы значений. Таким образом, он не подлежит сборке мусора, если только он не содержится как член типа объекта, тогда содержащий объект удаляется сборщиком мусора.

Remy Lebeau 19.06.2023 22:29

Другие вопросы по теме