我正在阅读一本教科书并遇到以下函数从链表中删除一个元素。 typedef struct CELL CELL;
struct CELL {
int element;
CELL* next;
};
void delete(int x, CELL** pL) {
if ((*pL) != NULL) {
if (x == (*pL)->element)
(*pL) = (*pL)->next;
else
delete(x, &((*pL)->next));
}
}
类型定义如下;
5->10->3->21->15->7
现在假设我有一个链接列表,其中包含从5开始的以下元素;
CELL
现在假设我删除了元素10.我的问题是当delete
函数返回此CELL
未被引用时,包含10的 Traceback (most recent call last):
File "script.py", line 1, in <module>
import tabula
File "/home/ubuntu/.local/lib/python2.7/site-packages/tabula/__init__.py", line 1, in <module>
from .wrapper import read_pdf_table
File "/home/ubuntu/.local/lib/python2.7/site-packages/tabula/wrapper.py", line 16, in <module>
import requests
ImportError: No module named requests
会发生什么?难道它还在占用内存空间吗?
答案 0 :(得分:2)
由于您没有释放代码中的任何内存,因此它应该仍然存在于某处。您只需将该元素与链接列表取消链接即可。
根据您管理这些元素的内存的方式,这可能是也可能不是问题(内存泄漏)。例如,如果使用malloc
分配每个元素,并且链接列表只有指向该元素的指针,那么您很可能会发生内存泄漏(并且需要使用free
)。但是如果节点在堆栈上分配(例如使用alloca
)或者在稍后释放的某个内存池中,则可能没有泄漏。所以它真正归结为你如何处理内存以及何时解除分配。
答案 1 :(得分:2)
当删除函数返回此
CELL
未引用时,包含10的CELL
会发生什么?它还在占用记忆中的空间吗?
绝对!一旦函数返回,包含10的CELL
就会成为内存泄漏,除非有另一个指针引用它,或者CELL
不是动态分配。
如果操作列表的其他功能(创建,插入等)以这样的方式实现,即它们假定列表对其单元格的所有权,则在分支中添加对free
的调用。将*pl
重新分配到(*pL)->next
。创建一个临时变量,将*pl
的地址存储在其中,重新指向,并在临时变量上调用free
。
答案 2 :(得分:1)
对于初学者来说,有关函数本身的一些评论。最好以下列方式声明函数
int delete( CELL **pL, int x );
实际上这个功能做了两件事。它搜索值等于x的节点。如果发现这样的话,它会取消链接节点。
因此,该函数最好报告是否找到了这样的节点。
在函数未释放注释中 @IanAbbott 指向的已移除节点的情况下声明函数的另一种方法是
CELL * delete( CELL **pL, int x );
这是函数返回指向已删除节点的指针,如果找不到值等于x的节点,则返回NULL。
其次,最好将第一个参数声明为节点的引用,将第二个参数声明为搜索值。这首先是你正在处理的事情,然后是你如何处理清单。
至于你的问题,那么我已经说过的功能取消了一个节点的链接。节点本身不会从内存中删除,也不会更改。如果它是动态分配的,那么您必须保留指向该节点的指针的副本。否则会出现内存泄漏,因为如果没有指向节点的指针,您将无法释放它。