我现在的程序有一个大问题。在on循环中,两个函数如果我在这个循环中再调用一个函数,就会得到一个永久循环!即使是printf("bah");
也会产生永久循环
给出正常的执行。
//size = 10 (example)
while(size > 0) {
a(); // decrement by 2
b(); // decrement by 2
}
,
//size = 10 (example)
while(size > 0) {
a(); // decrement by 2
b(); // decrement by 2
putchar(' ');
}
给出一个永久循环。唯一不同的是putchar()
调用。
很难假设一些事情,但是对正在发生的事情有一些想法吗?
a() and
b() '函数的基本功能是:
从数组中获得两个结构体,size
减去1
和printf()
中的一些成员。这样的结构(目前)只在程序结束时才释放。
我发布这部分代码是为了了解(可能)发生了什么。这部分代码的所有代码都非常大(要贴在这里供我们阅读)。
编辑:以下是a()
和b()
的最小实现:
void a(void) {
foo_t* f = top;
while(f->y == STATE_X) {
get(&a); get(&b); /* it's equivalent to pop() in a linked list. size is size=size-1 in each get call() */
printf("%d,%dn",a->x,ab->x);
f = f->next;
}
top = f;
}
void a(void) {
foo_t* f = top;
while(f->y == STATE_Y) {
get(&a); get(&b); /* it's equivalent to pop() in a linked list. size is size=size-1 in each get call() */
printf("%d,%dn",a->x,ab->x);
f = f->next;
}
top = f;
}
get()
-在我的上下文中相当于pop()
。
top
-指向最后一个从堆栈中处理的struct footype
。
size
-当前栈上元素的计数。
struct footype
也是这样实现的,有一个prev
和next
指向它的前一个和下一个成员。
如果我们完全按照你所说的代码去做——内存被分配了,但从未释放——那么内存将一直被分配,直到程序结束。如果你继续分配更多的内存而不释放,最终你会用完的…此时malloc
可能开始失败并返回空指针。(当然,如果我们按照C标准,尝试通过空指针访问内存可能会导致各种奇怪的事情随之而来。但是,在Linux中最常见的结果是段错误。
然而,如果没有ulimit
设置,您可能也会用完所有的交换空间,这可能会导致最终的巨大减速。当然,在你的进程中使用所有的内存,会从其他进程中占用内存。最终,可能会发生以下两种情况之一:
-
其他进程可能开始分配内存失败…如果他们没有考虑到这一点,他们可能会崩溃。
-
Linux会有意地分发虚拟内存——基本上,既不支持RAM也不支持交换空间的内存页。(这样做的原因有点复杂,但在上下文中是有意义的。)只有当一个进程试图实际使用内存时,内核才会为它清理一些RAM。如果没有可用的RAM和空间可以交换,内核将杀死一个现有的进程来回收它的虚拟内存。
(如果到这个程度,就会有一个算法来决定杀死哪个进程。它通常会选择内存占用最严重的进程——在这种情况下,可能是您的进程。
不过,这就是破坏的程度。你会减慢进程的速度,扰乱其他进程,并可能导致其中一个进程被杀死(很可能是你的进程)。
有一件事它不会做,至少它自己不会做,那就是让循环永远继续下去。为了引起这种情况,程序必须(1)检查失败,(2)永远循环重试失败的操作直到成功,而不改变与操作相关的任何内容。