Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ cli 什么情况促使.NET2.0字符串构造函数抛出异常?_C++ Cli_.net 2.0 - Fatal编程技术网

C++ cli 什么情况促使.NET2.0字符串构造函数抛出异常?

C++ cli 什么情况促使.NET2.0字符串构造函数抛出异常?,c++-cli,.net-2.0,C++ Cli,.net 2.0,我有一些代码,在使用Stringcostructor时,有时(但不总是)抛出中描述的异常 本质上,我的代码如下所示(除了输入字符串数组的长度因输入而异): kb文章指出,这“可能”导致抛出异常,但我的单元测试和大多数情况下,它从未出现 我想知道是什么引发了异常,这样我就可以在单元测试中复制它,并验证它在我们的代码库中是永久固定的。他们在4.0中修复了它,但在2.0中仍然被破坏: using System; using System.Runtime.InteropServices; namesp

我有一些代码,在使用
String
costructor时,有时(但不总是)抛出中描述的异常

本质上,我的代码如下所示(除了输入字符串数组的长度因输入而异):

kb文章指出,这“可能”导致抛出异常,但我的单元测试和大多数情况下,它从未出现


我想知道是什么引发了异常,这样我就可以在单元测试中复制它,并验证它在我们的代码库中是永久固定的。

他们在4.0中修复了它,但在2.0中仍然被破坏:

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication13
{
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr VirtualAlloc(IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);

        // For .NET 4.0
        //[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
        static unsafe void Main(string[] args)
        {
            IntPtr ptr = VirtualAlloc(
                IntPtr.Zero, 
                (IntPtr)(4096 * 2), 
                0x1000 /* MEM_COMMIT */ | 0x2000 /* MEM_RESERVE */, 
                0x04 /* PAGE_READWRITE */);

            IntPtr page1 = ptr;
            IntPtr page2 = (IntPtr)((long)ptr + 4096);

            uint oldAccess;
            bool res = VirtualProtect(page2, 4096, 0x01 /* PAGE_NOACCESS */, out oldAccess);

            try
            {
                Marshal.WriteByte(page1, 1);
                Console.WriteLine("OK");
            }
            catch (AccessViolationException)
            {
                Console.WriteLine("KO");
            }

            try
            {
                Marshal.WriteByte(page2, 1);
                Console.WriteLine("KO");
            }
            catch (AccessViolationException)
            {
                Console.WriteLine("OK");
            }

            try
            {
                byte b1 = Marshal.ReadByte(page1);
                Console.WriteLine("OK");
            }
            catch (AccessViolationException)
            {
                Console.WriteLine("KO");
            }

            try
            {
                byte b2 = Marshal.ReadByte(page2);
                Console.WriteLine("KO");
            }
            catch (AccessViolationException)
            {
                Console.WriteLine("OK");
            }

            for (int i = 0; i < 4096; i++)
            {
                Marshal.WriteByte(page1, i, (byte)'A');
            }

            sbyte* ptr2 = (sbyte*)page1;

            try
            {
                var st1 = new string(ptr2, 0, 4096);
                Console.WriteLine("OK");
            }
            catch (ArgumentOutOfRangeException)
            {
                Console.WriteLine("KO");
            }
        }
    }
}
使用系统;
使用System.Runtime.InteropServices;
命名空间控制台应用程序13
{
班级计划
{
[DllImport(“kernel32.dll”,SetLastError=true)]
静态外部IntPtr VirtualAlloc(IntPtr lpAddress、IntPtr dwSize、uint flAllocationType、uint flProtect);
[DllImport(“kernel32.dll”,SetLastError=true)]
静态外部布尔虚拟保护(IntPtr lpAddress、uint dwSize、uint flNewProtect、out uint lpflOldProtect);
//对于.NET4.0
//[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
静态不安全void Main(字符串[]args)
{
IntPtr ptr=VirtualAlloc(
IntPtr.Zero,
(IntPtr)(4096*2),
0x1000/*MEM_COMMIT*/| 0x2000/*MEM_RESERVE*/,,
0x04/*页(读写*/);
IntPtr page1=ptr;
IntPtr第2页=(IntPtr)((长)ptr+4096);
uint-oldAccess;
bool res=VirtualProtect(第2页,4096页,0x01/*PAGE\u NOACCESS*/,out oldAccess);
尝试
{
Marshal.WriteByte(第1页,第1页);
控制台。写入线(“OK”);
}
捕获(AccessViolationException)
{
控制台。写入线(“KO”);
}
尝试
{
封送员写入字节(第2页,第1页);
控制台。写入线(“KO”);
}
捕获(AccessViolationException)
{
控制台。写入线(“OK”);
}
尝试
{
字节b1=封送。读取字节(第1页);
控制台。写入线(“OK”);
}
捕获(AccessViolationException)
{
控制台。写入线(“KO”);
}
尝试
{
字节b2=封送。读取字节(第2页);
控制台。写入线(“KO”);
}
捕获(AccessViolationException)
{
控制台。写入线(“OK”);
}
对于(int i=0;i<4096;i++)
{
Marshal.WriteByte(第1页,i,(字节)'A');
}
sbyte*ptr2=(sbyte*)第1页;
尝试
{
var st1=新字符串(ptr2,0,4096);
控制台。写入线(“OK”);
}
捕获(ArgumentOutOfRangeException)
{
控制台。写入线(“KO”);
}
}
}
}
您必须在.NET 4.0中取消注释一行。请注意,这段代码并没有释放它分配的内存,但这不是一个大问题,因为当进程结束时,操作系统会回收内存

这个程序做什么?它使用
VirtualAlloc
分配8192字节(2页)。通过使用
VirtualAlloc
这两个页面是页面对齐的。它禁用对第二页的访问(使用
VirtualProtect
)。然后它用
'A'
填充第一页。然后它尝试从第一页创建一个
字符串。在.NET2.0上,
string
构造函数尝试读取第二页的第一个字节(即使您告诉它字符串只有4096字节长)

在中间有一些测试,检查页面是否可以读/写


通常很难检查这种情况,因为很难在分配的可读内存空间的末尾有一个内存块。

他们在4.0中修复了它,在2.0中仍然中断:

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication13
{
    class Program
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr VirtualAlloc(IntPtr lpAddress, IntPtr dwSize, uint flAllocationType, uint flProtect);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);

        // For .NET 4.0
        //[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
        static unsafe void Main(string[] args)
        {
            IntPtr ptr = VirtualAlloc(
                IntPtr.Zero, 
                (IntPtr)(4096 * 2), 
                0x1000 /* MEM_COMMIT */ | 0x2000 /* MEM_RESERVE */, 
                0x04 /* PAGE_READWRITE */);

            IntPtr page1 = ptr;
            IntPtr page2 = (IntPtr)((long)ptr + 4096);

            uint oldAccess;
            bool res = VirtualProtect(page2, 4096, 0x01 /* PAGE_NOACCESS */, out oldAccess);

            try
            {
                Marshal.WriteByte(page1, 1);
                Console.WriteLine("OK");
            }
            catch (AccessViolationException)
            {
                Console.WriteLine("KO");
            }

            try
            {
                Marshal.WriteByte(page2, 1);
                Console.WriteLine("KO");
            }
            catch (AccessViolationException)
            {
                Console.WriteLine("OK");
            }

            try
            {
                byte b1 = Marshal.ReadByte(page1);
                Console.WriteLine("OK");
            }
            catch (AccessViolationException)
            {
                Console.WriteLine("KO");
            }

            try
            {
                byte b2 = Marshal.ReadByte(page2);
                Console.WriteLine("KO");
            }
            catch (AccessViolationException)
            {
                Console.WriteLine("OK");
            }

            for (int i = 0; i < 4096; i++)
            {
                Marshal.WriteByte(page1, i, (byte)'A');
            }

            sbyte* ptr2 = (sbyte*)page1;

            try
            {
                var st1 = new string(ptr2, 0, 4096);
                Console.WriteLine("OK");
            }
            catch (ArgumentOutOfRangeException)
            {
                Console.WriteLine("KO");
            }
        }
    }
}
使用系统;
使用System.Runtime.InteropServices;
命名空间控制台应用程序13
{
班级计划
{
[DllImport(“kernel32.dll”,SetLastError=true)]
静态外部IntPtr VirtualAlloc(IntPtr lpAddress、IntPtr dwSize、uint flAllocationType、uint flProtect);
[DllImport(“kernel32.dll”,SetLastError=true)]
静态外部布尔虚拟保护(IntPtr lpAddress、uint dwSize、uint flNewProtect、out uint lpflOldProtect);
//对于.NET4.0
//[System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptions]
静态不安全void Main(字符串[]args)
{
IntPtr ptr=VirtualAlloc(
IntPtr.Zero,
(IntPtr)(4096*2),
0x1000/*MEM_COMMIT*/| 0x2000/*MEM_RESERVE*/,,
0x04/*页(读写*/);
IntPtr page1=ptr;
IntPtr第2页=(IntPtr)((长)ptr+4096);
uint-oldAccess;
bool res=VirtualProtect(第2页,4096页,0x01/*PAGE\u NOACCESS*/,out oldAccess);
尝试
{
Marshal.WriteByte(第1页,第1页);
控制台。写入线(“OK”);
}
捕获(AccessViolationException)
{
控制台。写入线(“KO”);
}
尝试
{
封送员写入字节(第2页,第1页);
控制台。写入线(“KO”);
}
捕获(AccessViolationException)
{
控制台。写入线(“OK”);
}
尝试
{
字节b1=封送。读取字节(第1页);
控制台。写入线(“OK”);
}
捕获(AccessViolationException)
{
控制台。写入线(“KO”);
}
   if( IsBadReadPtr(pszSource, (UINT_PTR)length + 1)) {
       COMPlusThrowArgumentOutOfRange(L"ptr", L"ArgumentOutOfRange_PartialWCHAR");
   }
LPVOID ptr = VirtualAlloc(0, 4096 * 2, 0x1000, 0x04); // ReadWrite

LPVOID page1 = ptr;
LPVOID page2 = (LPVOID)((long)ptr + 4096);

DWORD oldAccess;
bool res = VirtualProtect(page2, 4096, 0x01, &oldAccess);

char* ptr2 = (char*)page1;

String^ st1 = gcnew String(ptr2, 0, 4096); // <-- This will cause the exception.

Console::WriteLine(st1);