为什么会陷入死循环

本文通过两个实例深入解析了在C语言程序中,由于栈中变量存储顺序不当导致的死循环现象及其原因。首先介绍了变量在内存中的布局方式,接着详细分析了因变量覆盖引发的无限循环问题。
看似简单的一段程序如下:
 int main()
{
   int i,j[8];
   for(i=0;i<=8;i++)
    j[i]=0;
   return 0;

    在UNIX/Linux平台下,gcc编译运行会陷入死循环.  
 
    因为变量 i 和数组 j[8]是保存在栈中,默认是由高地址向低地址方向存储. 输出变量地址可以发现: i 存储位置在0xbfd90dec, j[0]、j[1]...j[7]在内存的地址分别是0xbfdab05c、0xbfdab060,...0xbfdab078. 如下所示:
          高地址 <--------------------------------------->低地址
                           i,j[7],j[6],j[5],j[4],j[3],j[2],j[1],j[0]
 
    如果在int i,j[8]后面再定义变量int c,那么c就存放在j[0]的往低方向的下一个地址0xbfdab058 .

      现在不难理解这段程序为什么会出现死循环了。j[8]的位置就是变量i所在的位置。这样当i=8时的j[i]=0语句,实际上就是将i的值置为0,然后 i 又从0到8循环一直下去.  如果将原句改为int j[8],i; 就不会出现死循环,而仅仅是一个段越界错误.

另一个程序:
#include <stdio.h>
int main()
{
        int i;
        char c;
        for(i=0;i<5;i++)
        {
                scanf("%d",&c);
                printf("i=%d ",i);
        }
        printf("/n");
}
编译后运行
[foxman@local~]#./a.out
0    (输入0)
i=0  (输出 i 值)
1
i=0
2
i=0
3
i=0
4
i=0
...
这样一直循环下去。

问 题在于,c被声明为char类型,而不是int类型。当程序要求scanf读入一个整数时,应该传递给它一个指向整数的指针。而程序中scanf得到的却 是一个指向字符的指针,scanf函数并不能分辨这种情况,只能将这个指向字符的指针作为指向整数的指针而接受,并且在指针指向的位置存储一个整数。 因为整数所占的存储空间要大于字符所占的存储空间,所以c附近的内存会被覆盖.

由上面分析,i 和 c 是由高地址到低地址存储在栈中,这样在c所在位置尝试存储一个4字节变量,会占用比c高的3个字节(覆盖掉 i 字节的低3位),即使 i 总是为零,一直循环下去.

如果每次输入Ctrl+D作为字符终止符不存储int到c处,那么就会输出正常i=0..4了.
 
Python 代码陷入 **死循环(Infinite Loop)** 的原因是:**循环条件永远为真(True)**,导致程序无法退出循环。 --- ## ✅ 一、常见导致死循环的场景 ### 1. `while True` 但没有 `break` 或退出机制 ```python while True: print("Hello") ``` 这个循环会 **无限打印 "Hello"**,因为 `while True` 永远为真。 ### ✅ 正确做法(加退出机制): ```python count = 0 while True: print("Hello") count += 1 if count >= 3: break ``` --- ### 2. `while` 条件永远不会变为 False ```python x = 5 while x > 0: print(x) x += 1 # x 会越来越大,永远大于 0 ``` 这段代码中,`x` 每次增加 1,所以 `x > 0` 永远为真,导致死循环。 --- ### 3. 忘记更新循环变量 ```python i = 0 while i < 10: print(i) # 忘记写 i += 1 ``` 变量 `i` 始终为 0,循环条件 `i < 10` 永远成立。 --- ### 4. `for` 循环遍历无限迭代器(需配合 `itertools`) ```python import itertools for i in itertools.count(): print(i) ``` `itertools.count()` 会无限生成数字,导致 `for` 循环永不停止。 --- ## ✅ 二、如何避免死循环? ### ✅ 建议做法: 1. **使用 `for` 循环代替 `while` 循环(如果知道循环次数)** 2. **确保 `while` 条件最终会变为 False** 3. **设置最大循环次数或超时机制** 4. **在无限循环中加入 `break` 退出机制** --- ## ✅ 三、死循环的调试技巧 1. **打印变量值**:查看循环变量是否变化 2. **使用调试器(如 PyCharm、VS Code)** 3. **使用 `Ctrl+C` 强制终止程序** 4. **添加计数器防止无限循环** ```python count = 0 while condition: # 做一些事 count += 1 if count > 1000: print("循环超过1000次,可能死循环") break ``` --- ## ✅ 四、死循环的用途(有意为之) 有时候我们会故意使用死循环,比如: ### 1. 网络服务器监听客户端请求 ```python while True: client, addr = server.accept() handle_client(client) ``` ### 2. 游戏主循环 ```python while True: handle_events() update_game() render() ``` ### 3. 定时任务 ```python import time while True: do_something() time.sleep(60) # 每分钟执行一次 ``` --- ## ✅ 总结 | 原因 | 是否常见 | 示例 | |------|----------|------| | `while True` 没有退出机制 | ✅ 是 | `while True: print("死循环")` | | 循环条件永远为真 | ✅ 是 | `while x > 0: x += 1` | | 忘记更新循环变量 | ✅ 是 | `i = 0; while i < 10: ...` | | 使用无限迭代器 | ✅ 是 | `itertools.count()` | --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值