我正在尝试创建一个模拟数组的类,并使用指针。一切正常,直到我的指针值被覆盖。
这是我的代码示例,这是我用来获取/设置值的索引器。正如我所说的那样一切正常,直到某个时候地址被其他一些随机值覆盖。
我如何修复或"保留"空间表示"数组的长度"?
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;
答案 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错误和朋友吗?),会导致随机问题。确保您了解下层的工作方式 - 使用不安全的代码,这些抽象可以帮助您避免理解消失。低级编码不是很友好。