在C#(不安全构造)中使用结构实现链表时获取垃圾值
我试图验证我的一个朋友报告的行为,所以我使用struct在C#中实现了单链表。因为我必须使用指针,所以我使用了C#提供的不安全构造。我还在项目属性的build选项卡中将属性设置为在C#(不安全构造)中使用结构实现链表时获取垃圾值,c#,struct,unsafe,C#,Struct,Unsafe,我试图验证我的一个朋友报告的行为,所以我使用struct在C#中实现了单链表。因为我必须使用指针,所以我使用了C#提供的不安全构造。我还在项目属性的build选项卡中将属性设置为允许不安全代码,以使代码可编译 以下是我的完整代码实现: public unsafe struct NodeList { public Node* head; public Node* current; public void AddNode(int d) { Node
允许不安全代码
,以使代码可编译
以下是我的完整代码实现:
public unsafe struct NodeList
{
public Node* head;
public Node* current;
public void AddNode(int d)
{
Node n = new Node();
n.data = d;
n.link = null;
if (head == null)
{
head = current = &n;
}
else
{
(*current).link = &n;
current = &n;
}
Console.WriteLine(head->data);
}
public void TraverseNodes()
{
Node* temp = head;
while(temp != null)
{
Console.WriteLine(temp -> data);
temp= temp -> link;
}
}
}
public unsafe struct Node
{
public int data;
public Node* link;
}
class Program
{
private static void UnsafeDSImplementation()
{
var myLinkedList = new NodeList();
myLinkedList.AddNode(2);
myLinkedList.AddNode(4);
myLinkedList.TraverseNodes();
}
static void Main(string[] args)
{
UnsafeDSImplementation();
}
}
错误的观察:
AddNode
方法并尝试打印节点数据值时,第一次得到2,第二次得到4。我想知道,当我在添加第一个节点时只分配一次头时,头为什么会改变System.nullreferenceexception
exception。两个节点都应正确打印数据现在,我得到的行为可能是由于我在代码中犯了一个错误,也可能是因为我使用的是托管世界中的指针。我需要您的帮助来解决这个问题。使用本机
封送.AllocHGlobal
分配内存(类似于C中的malloc)
注意:您还需要使用
封送。FreeHGlobal
释放内存。当head为null时,head和current都指向相同的内存位置。所以两者都成为指向相同内存地址的指针。
添加第二个节点时,您正在更改当前指针指向的值,但由于头部也指向相同的值,所以它也会随当前值而更改
我是通过阅读您的代码得出这个结论的,所以我可能不正确。但是这似乎是原因。为什么C标签是C??这个问题和C或C++有什么关系?请不要用不相关的标签发送垃圾邮件。已更新的标签。删除C和C++。我认为这是关于指针和不安全的东西,所以添加了C和C++。至于你的问题,在<代码> AddNode < /C> >不是函数<代码> n>代码>函数中的局部变量,一个函数返回后的范围内的局部变量?发生这种情况时,指向该局部变量的指针会发生什么情况?它们指向哪里?您正在存储指向堆栈分配变量的指针,因此得到垃圾也就不足为奇了代码>。在函数内部执行此操作本质上是在堆栈上进行内存分配,因为
节点是一个结构。函数结束时,内存分配消失,因为堆栈顶部指针将向后移动。您无法控制在未分配的孤立内存区域上写入的内容。我不得不使用Richa的Node*newNode=(Node*)Marshal.AllocHGlobal(sizeof(Node)).ToPointer()
code在程序的Heap
内存区域上进行分配,以在AddNode
函数执行完成后将其持久化。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Linked_List
{
public unsafe class NodeList
{
public static Node * head ;
public void AddNode(int d)
{
Node* newNode = (Node*)Marshal.AllocHGlobal(sizeof(Node)).ToPointer();
newNode->data = d;
newNode->link = null;
Node* temp;
if (head == null)
{
head = newNode;
}
else
{
temp = head;
head = newNode;
newNode->link = temp;
}
Console.WriteLine(head->data);
}
public void TraverseNodes()
{
Node* temp = head;
while (temp != null)
{
Console.WriteLine(temp->data);
temp = temp->link;
}
}
}
public unsafe struct Node
{
public int data;
public Node* link;
}
unsafe class Program
{
private static void UnsafeDSImplementation()
{
var myLinkedList = new NodeList();
myLinkedList.AddNode(2);
myLinkedList.AddNode(4);
myLinkedList.TraverseNodes();
}
static void Main(string[] args)
{
UnsafeDSImplementation();
}
}
}