代码之家  ›  专栏  ›  技术社区  ›  Adeel

协助我处理这个C指针代码

  •  0
  • Adeel  · 技术社区  · 15 年前

    我正在发布代码。

    using System;
    using System.Runtime.InteropServices;
    class TestPointer
    {
        public static void Main(string[] args)
        {        
            if (args.Length == 0)
            {
                unsafe
                {
                    int t = 8;
                    int* p = &t;
                    IntPtr addr = (IntPtr)p;
    
                    Console.WriteLine(addr.ToString("x"));
                    Console.WriteLine("before: " +(*p));
                    Console.ReadLine();
                    Console.WriteLine("after: " + (*p));
                }
            }
            else
            {
                unsafe
                {
                    string str = args[0];
                    GCHandle handle = GCHandle.Alloc(str, GCHandleType.Pinned);
                    IntPtr pointer = GCHandle.ToIntPtr(handle);
    
                    int* p = (int*)pointer;
                    int t = 5;
                    p = &t;
    
                    Console.WriteLine((*p));
                }
            }
        }
    }
    

    我在两个实例中运行了此代码。

    在instance1中,我调用了testpointer.exe,instance1显示内存位置8,而不是console.readline()语句中停止的execuion。在下一步中,我使用testpointer.exe 12f470(从instance1显示的内存地址)运行另一个实例(instance2),因此在本例中,我将值从8更改为5,并在从instance1读取行后更改。 应显示值5,但仍显示8。原因是什么?

    3 回复  |  直到 10 年前
        1
  •  1
  •   Jon Skeet    15 年前

    这两个进程有两个不同的虚拟地址空间。如果一个进程不显式地执行某种共享(内存映射文件等),就可以在另一个进程中踩踏值,我会非常震惊。

    这是在教育上的练习,还是有什么你想要达到的目标,而这只是一个初步的尝试?如果是后者,请详细说明您要做什么。

        2
  •  1
  •   Dave Markle    15 年前

    首先,内存在实例之间是孤立的。这在MS-DOS时代是不正确的,但现在,它是每个现代操作系统的“主要指令”。

    因此,您将永远无法以这种方式跨实例通信数据。

    另一方面,内存分配器并不保证一旦调用内存,它将在同一个地方分配内存——远离它。我的建议是远离硬编码地址。

    从一个角度来看…似乎您需要学习很多关于操作系统、CLR和内存管理的基础知识。对我来说,这意味着你不应该触及“不安全”的结构。你在玩火。这是一个高级构造,主要用于与旧代码库的互操作性。我的建议是远离它。

        3
  •  0
  •   Eugene Pankov    15 年前

    原因是您无法如此轻松地访问另一个进程的内存。 这被称为“虚拟内存”,这是现代操作系统保护运行进程内存不受损坏的方式。