用这个C#指针代码帮我

时间:2010-02-16 11:18:39

标签: c# pointers

我正在发布一个代码。

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,实例1显示内存位置为8,而执行停止在Console.ReadLine()语句中。在下一步中,我运行另一个实例(instance2)与TestPointer.exe 12f470(实例1中显示的内存地址),所以在这种情况下,我将值从8更改为5,并在read1之后从instance1更改 应该显示值5,但它仍然显示8.原因是什么?

3 个答案:

答案 0 :(得分:1)

这两个进程有两个不同的虚拟地址空间。如果一个进程可以在没有明确执行某种共享(内存映射文件等)的情况下踩踏另一个进程中的值,我会感到非常恐惧。

这是一项教育活动,还是你想要实现的目标,这只是一次初步尝试?如果是后者,请向我们提供有关您正在尝试做的更多详细信息。

答案 1 :(得分:1)

嗯,首先,实例之间的内存是隔离的。在MS-DOS时代,情况并非如此,但如今,它是每个现代操作系统的“主要指令”。

因此,您永远无法以这种方式跨实例传递数据。

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

这里有点透视......看起来你需要学习很多关于操作系统,CLR和内存管理的基础知识。对我来说,这意味着你不应该触及“不安全”的结构。你正在玩火。它是一种高级构造,主要用于与旧代码库的互操作性。我的建议是远离它。

答案 2 :(得分:0)

原因是您无法轻易访问其他进程的内存。 这就是所谓的“虚拟内存”,它是现代操作系统保护运行进程内存免受损坏的方式。