英文:
Access Violation Exception 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,但没有产生结果。
英文:
I don't understand what is causing this error
[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);
}
}
}
I tried in Visual Studio to change the build type from Any CPU to x86, but it didn't bring results.
答案1
得分: 0
EnterCriticalSection()
需要接收一个已经使用 InitializeCriticalSection()
或 InitializeCriticalSectionAndSpinCount()
初始化过的 CRITICAL_SECTION
结构体的指针作为参数。
但是,您却传递了一个未初始化的 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);
}
}
}
然而,在C#中,您实际上不需要使用 CRITICAL_SECTION
,可以使用 lock
语句 或者类似 System.Threading.Monitor
的同步原语。
英文:
EnterCriticalSection()
expects to be given a pointer to a CRITICAL_SECTION
struct that has been initialized with either InitializeCriticalSection()
or InitializeCriticalSectionAndSpinCount()
.
But instead, you are giving it a reference to an uninitialized IntPtr
that doesn't point anywhere meaningful. Hence the crash when EnterCriticalSection()
tries to access a struct that doesn't exist.
The correct code should look more like this:
[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);
}
}
}
However, you really don't need to use CRITICAL_SECTION
in C#, use the lock
statement instead, or a synchronization primitive like System.Threading.Monitor
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论