使用指针,内存被覆盖,如何"保留"记忆?

时间:2016-03-16 16:26:33

标签: c#

我正在尝试创建一个模拟数组的类,并使用指针。一切正常,直到我的指针值被覆盖

这是我的代码示例,这是我用来获取/设置值的索引器。正如我所说的那样一切正常,直到某个时候地址被其他一些随机值覆盖。

我如何修复或"保留"空间表示"数组的长度"?

public int this[int x]
    {
        get
        {
            if(x >= _length || x < 0)
            {
                throw new IndexOutOfRangeException();
            }
            int* offsetToReturn = indexZeroPointer + x;

            return *offsetToReturn;
        }
        set
        {
            if (x >= _length || x < 0)
            {
                throw new IndexOutOfRangeException();
            }

            int* offset = indexZeroPointer + x;

            *offset = value;
        }
    }

我将数组的索引0用作我在类中声明的随机整数的地址。

indexZeroPointer = &someValue;

1 个答案:

答案 0 :(得分:4)

您不能随便随机获取C#中的对象地址。您处于托管内存环境中,虚拟内存空间中的位置可以(并且将会)发生变化。

通过获取单个整数的地址,您最多 获取要使用的四个字节的内存。你不能只是访问背后的内存并希望最好 - 不仅会改变(由于内存重定位),它也会被其他人占用。如果从本地获取地址(尤其是在堆栈中分配),则尤其如此 - 您将无缘无故地重写堆栈。

如果要(相对)安全地使用指针,则需要确保您使用的内存实际上是已分配,并且只要有必要就会保留。例如,如果您事先知道长度,则可以使用这段代码来获取“零地址”:

"<eventNotification>" +
                    "<url>" +
                        Tyc.Website.Properties.Settings.Default.DocusignStatusAPIUrl +
                    "</url>" +
                    "<loggingEnabled>" +
                        true +
                    "</loggingEnabled>" +
                    "<requireAcknowledgment>" +
                        true +
                    "</requireAcknowledgment>" +
                    "<includeDocuments>" +
                        true +
                    "</includeDocuments>" +
                    "<EnvelopeEvents>" +
                        "<envelopeEvent>" +
                            "<envelopeEventStatusCode>" + "Completed" + "</envelopeEventStatusCode>" +
                            "<includeDocuments>" + true + "</includeDocuments>" +
                        "</envelopeEvent>" +
                        "<envelopeEvent>" +
                             "<envelopeEventStatusCode>" + "Sent" + "</envelopeEventStatusCode>" +
                             "<includeDocuments>" + true + "</includeDocuments>" +
                        "</envelopeEvent>" +
                        "<envelopeEvent>" +
                             "<envelopeEventStatusCode>" + "Delivered" + "</envelopeEventStatusCode>" +
                             "<includeDocuments>" + true + "</includeDocuments>" +
                        "</envelopeEvent>" +
                        "<envelopeEvent>" +
                             "<envelopeEventStatusCode>" + "Sent" + "</envelopeEventStatusCode>" +
                             "<includeDocuments>" + true + "</includeDocuments>" +
                        "</envelopeEvent>" +
                        "<envelopeEvent>" +
                             "<envelopeEventStatusCode>" + "Sent" + "</envelopeEventStatusCode>" +
                             "<includeDocuments>" + true + "</includeDocuments>" +
                        "</envelopeEvent>" +
                    "</EnvelopeEvents>" +
                    "<RecipientEvents>" +
                        "<recipientEvent>" +
                            "<includeDocuments>" + true + "</includeDocuments>" +
                            "<recipientEventStatusCode>" + "Sent" + "</recipientEventStatusCode>" +
                        "</recipientEvent>" +
                        "<recipientEvent>" +
                            "<includeDocuments>" + true + "</includeDocuments>" +
                            "<recipientEventStatusCode>" + "Delivered" + "</recipientEventStatusCode>" +
                        "</recipientEvent>" +
                        "<recipientEvent>" +
                            "<includeDocuments>" + true + "</includeDocuments>" +
                            "<recipientEventStatusCode>" + "Completed" + "</recipientEventStatusCode>" +
                        "</recipientEvent>" +
                        "<recipientEvent>" +
                            "<includeDocuments>" + true + "</includeDocuments>" +
                            "<recipientEventStatusCode>" + "AutoResponded" + "</recipientEventStatusCode>" +
                        "</recipientEvent>" +
                    "</RecipientEvents>" +
                "</eventNotification>"

但这只是你问题的开始。只要输入指针区域,就会失去处理托管内存的所有好处。你需要根据需要释放内存,摆脱无效或悬空指针,处理所有边界检查和许多其他。

这是另一个主题,只是感觉你的方式会伤害你。您真的想学习您正在做什么,以及计算机和操作系统的体系结构如何工作,以及所有这些如何与.NET内存模型集成。正如您刚刚发现的那样,不安全的代码会出现工作的倾向,如果您不知道自己在做什么(即使您这样做了 - 还记得Heartbleed错误和朋友吗?),会导致随机问题。确保您了解下层的工作方式 - 使用不安全的代码,这些抽象可以帮助您避免理解消失。低级编码不是很友好。