标签:
虽然C语言用了挺久,自以为指针也学的不错。最近都在写O-C,最近开始重拾C语言,发现自己关于C中的堆栈并没有完全理解。
C中的函数malloc:
struct ListNode* head = (struct ListNode *)malloc(sizeof(struct ListNode));
malloc()从堆里面获得空间,将这块堆空间的地址赋值给指针。也就是说函数返回的指针是指向堆里面的一块内存。操作系统中有一个记录空闲内存地址的链表。当操作系统收到程序的申请时,就会遍历该链表,然后就寻找第一个空间大于所申请空间的堆结点,然后就将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。
堆是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
栈是线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立。每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。
因此,当我们想要在函数返回数组、链表等数据结构时,需要动态申请内存(申请堆内存)。因为正常的栈内存(保存当前函数的运行状态,局部变量)都会在程序返回return后自动释放。我们返回的指针所指向的内容也会被释放,如果我们接着访问这个已经被释放的内存,就会造成内存泄漏,访问非法等,造成程序崩溃。
下面说一下我之前犯的错误。
函数需要返回一个链表(已知有n个节点)
//cur1和cur2为两个节点,2节点值的和为当前节点的值 struct ListNode* head = (struct ListNode *)malloc(sizeof(struct ListNode)); int val=0; int digit = 0; pre = head; //先分配空间 再用(地址值为右值) while (cur1 && cur2) { //rear = new(struct ListNode); rear = (struct ListNode *)malloc(sizeof(struct ListNode)); val = cur1->val + cur2->val +digit; rear->val = val%10;//本位 digit = val/10; cur1 = cur1->next; cur2 = cur2->next; pre->next = rear; pre = rear; }
一个一个节点的申请,再将它们连起来。此处,需要先申请节点的空间,再将上一个节点的next指针指向它。
我的错误为:
struct ListNode* head = (struct ListNode *)malloc(sizeof(struct ListNode)); int val=0; int digit = 0; pre = head; while (cur1 && cur2) { val = cur1->val + cur2->val +digit; pre->val = val; cur1 = cur1->next; cur2 = cur2->next; pre= pre->next;//错误在此处。pre->next为null,赋值后pre为null pre= (struct ListNode *)malloc(sizeof(struct ListNode));//pre指向堆某块内存,但此时并没有节点指向pre所在的节点
}
后两句改一下就对了。
//先分配空间 再用(地址值为右值)!! pre->next= (struct ListNode *)malloc(sizeof(struct ListNode));
pre = pre->next;
标签:
原文地址:http://www.cnblogs.com/Anthea-i/p/4774303.html