Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.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# 读写记忆什么时候是合法的?_C#_Pointers_Memory - Fatal编程技术网

C# 读写记忆什么时候是合法的?

C# 读写记忆什么时候是合法的?,c#,pointers,memory,C#,Pointers,Memory,如果我错了,请纠正我。我问这个问题是为了澄清我的一些想法 今天在学校我学到了当一个进程(程序)执行时,操作系统会给它一个内存空间。以这两个项目为例: 程序1: static void Main(string[] args) { unsafe // in debug options on the properties enable unsafe code { int a = 2; int* poi

如果我错了,请纠正我。我问这个问题是为了澄清我的一些想法

今天在学校我学到了当一个进程(程序)执行时,操作系统会给它一个内存空间。以这两个项目为例:

程序1:

    static void Main(string[] args)
    {

        unsafe // in debug options on the properties enable unsafe code
        {

            int a = 2;

            int* pointer_1 = &a; // create pointer1 to point to the address of variable a

            // breakpoint in here !!!!!!!!!!!!!!!!!

            // in the debug I should be able to see the address of pointer1. Copy it and 
            // type it in the console

            string hexValue = Console.ReadLine();

            // convert the hex value to base 10
            int decValue = int.Parse(hexValue, System.Globalization.NumberStyles.HexNumber);

            // create a new pointer that point to the address that I typed in the console
            IntPtr pointer_2 = new IntPtr(decValue);

            Console.WriteLine("The address of a: {0} Value {1}", ((int)&a), a);

            try
            {
                Console.WriteLine("The address of {0} points to value {1}", (int)&pointer_1, (int)pointer_2);

                // different approach of acomplishing the same
                Console.WriteLine(Marshal.ReadInt32(pointer_2));
            }
            catch
            {
                Console.WriteLine(@"you are supposed to be debuging this program.");                    
            }

        }
计划2

    static void Main(string[] args)
    {            
        unsafe
        {
            IntPtr pointer_0 = new IntPtr(95151860); // see address of variable from program1
            int* pointer_1 = (int*)pointer_0;
            // try to access program's 1 object
            Console.WriteLine("addrees of {0} points to value {1} ", (int)&pointer_1, *pointer_1); 
        }
    }

所以我知道在程序2中我会得到一个错误。我将访问受限内存。到目前为止,我所学到的是有意义的

好的,知道这里是没有意义的地方。

有一个非常好的程序叫做“用于自动化任务”。例如,它可以发送鼠标点击、移动鼠标、发送按键等

无论如何,autoit附带了一个名为autoit Window Info的程序,该程序使您能够获取windows上控件的句柄(指针)。例如,我可以通过将finder工具拖动到我希望获取信息的控件来查看窗口控件的句柄:

在这张图片中,我将finder工具拖动到计算器的输入控件。例如,我也可以将其拖动到按钮7

因此,如果您在图片中看到,我现在有了该控件的地址。然后我就可以从我的程序中访问它了


另一个例子是如何访问不属于我的程序的内存

步骤1)获取带有autoit窗口信息的任何窗口的指针

步骤2)在我的计算机中,指针是:

这是谷歌浏览器的窗口,我在这里输入这个问题

此类将在后面发送一个窗口:

    public static class SendWndToBack
    {
        [DllImport("user32.dll")]
        static extern bool SetWindowPos(
            IntPtr hWnd,
            IntPtr hWndInsertAfter,
            int X,
            int Y,
            int cx,
            int cy,
            uint uFlags);

        const UInt32 SWP_NOSIZE = 0x0001;
        const UInt32 SWP_NOMOVE = 0x0002;
        const UInt32 SWP_NOACTIVATE = 0x0010;

        static readonly IntPtr HWND_BOTTOM = new IntPtr(1);

        static readonly IntPtr k = new IntPtr(12);

        public static void WindowHandle(IntPtr windowHandle)
        {
            SetWindowPos(windowHandle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
        }            
    }
然后,如果我用我刚刚在autoit的帮助下得到的poniter调用该方法,并将其称为:

            SendWndToBack.WindowHandle(new IntPtr(0x00000000000510B2));
那我就把那扇窗户移到后面去


我举了一些例子来说明我的观点。但我的问题是什么时候可以访问内存的其他部分?如果我将我的变量公开,其他程序将能够访问它?为什么我可以从自己的程序中访问windows的某些控件?

您混淆了“句柄”和“指针”。 只是因为它看起来像一个地址,它可能不是。 Windows使用很多句柄,操作系统可能允许您对句柄执行操作,即使您没有创建它们。
您可以将句柄表示为IntPtr,但如果将其直接作为指针处理,则可能会崩溃。

那么什么是句柄?你的回答很有道理,谢谢!句柄只是一个ID。在窗口的情况下,操作系统将在某处有一个窗口列表,当调用SendWndToBack(ID)时,它将搜索具有该ID的窗口,然后对其执行“操作系统魔术”将其发送到后面。