mfc程序长时间运行后报错:a required resource was unavailable

本文详细解析了在OnPaint()和OnCtrlColor函数中因GDI资源管理不当导致的资源泄漏问题。通过调整代码,将局部变量的画刷句柄改为成员变量,并正确释放资源,有效解决了GDI资源不断累积的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://blog.youkuaiyun.com/thanklife/article/details/79350936

 

原因是设置背景色时用到了GDI资源,程序刚开始运行的时候没问题,但随着时间的蔓延,GDI资源耗尽,则报错:a required resource was unavailable。

GDI资源使用数量可在任务管理器中查看。

也就是说GDI资源泄漏的问题。

 

 

接着找到用到GDI资源的地方,主要代码如下(在OnPaint()中): 

 

if(nCtlColor == CTLCOLOR_STATIC)  //针对所有的标签
{
//pDC->SetBkMode(TRANSPARENT);
pDC->SetBkColor(RGB(78,78,78)); 
pDC->SetTextColor(RGB(255,255,255));

//return (HBRUSH)::GetStockObject(NULL_BRUSH);
//return (HBRUSH)::GetStockObject(DKGRAY_BRUSH);
HBRUSH myhbr= CreateSolidBrush(RGB(85,85,85));  
return myhbr;
}

 

将任务管理器中GDI对象打开,专门查看程序的GDI资源利用情况,发现只要程序一产生一个重绘事件(比如我拖动,拖动任务管理器窗口,放大缩小程序窗口),GDI资源就会增多。这种现象表示问题十有八九在OnPaint()函数中,但是我将程序用到的所有OnPaint()函数都查看过了,没什么可疑的,再次排查时,突然想到OnCtrlColor函数也会在界面刷新时调用,一查看果然发现问题,OnCtrlColor里返回的画刷的句柄因为是局部变量而没有被释放,改为成员变量,作如下修改后,解决问题

 

if(nCtlColor == CTLCOLOR_STATIC)  //针对所有的标签
{
//pDC->SetBkMode(TRANSPARENT);
pDC->SetBkColor(RGB(78,78,78)); 
pDC->SetTextColor(RGB(255,255,255));

//return (HBRUSH)::GetStockObject(NULL_BRUSH);
//return (HBRUSH)::GetStockObject(DKGRAY_BRUSH);
//HBRUSH myhbr= CreateSolidBrush(RGB(85,85,85));  
//return myhbr;


m_brBrush.DeleteObject();
m_brBrush.CreateSolidBrush(RGB(85,85,85));
return static_cast <HBRUSH> (m_brBrush.GetSafeHandle());

}

 

原文:http://blog.youkuaiyun.com/zhengyanan815/article/details/53201574

<think>我们正在处理一个Android编译错误:FAILED: posix_spawn: Resource temporarily unavailable 这个错误通常与系统资源限制有关,特别是在并行编译(如使用make -j或ninja)时,进程数或文件描述符数可能达到系统限制。 根据引用[4]和[5],这类错误往往是由于用户进程数达到上限(maxuproc)或文件描述符限制(ulimit -n)引起的。 因此,我们可以从以下几个方面进行排查和解决: 1. 检查并增加用户进程数限制(max user processes) 在Linux系统中,可以通过`ulimit -u`查看当前用户的进程数限制。编译时可能会启动大量子进程,如果限制太低,就会导致资源不可用。 临时增加:`ulimit -u 2048`(需要先退出编译环境,然后重新进入) 永久增加:修改/etc/security/limits.conf文件,添加: * soft nproc 2048 * hard nproc 4096 2. 检查并增加文件描述符限制(open files) 同样使用`ulimit -n`查看当前限制。编译过程中会打开大量文件,如果不够用也会报错。 临时增加:`ulimit -n 4096` 永久增加:在/etc/security/limits.conf中添加: * soft nofile 4096 * hard nofile 8192 3. 检查系统级别的进程限制(maxuproc) 对于整个系统的最大进程数,可以通过`sysctl kernel.pid_max`查看,如果系统总进程数接近上限,也可能影响。 修改:`sudo sysctl -w kernel.pid_max=65535` 4. 调整并行编译的进程数 如果上述方法不能解决,可以尝试减少并行编译的进程数,例如将make的-j参数调小,或者使用ninja时指定-j。 例如:`make -j4` 或者 `ninja -j4` 5. 检查内存和交换空间 编译过程中内存不足也可能导致资源不可用。确保有足够的物理内存和交换空间(swap)。可以通过`free -h`查看。 如果内存不足,可以尝试增加交换空间,或者减少并行编译的进程数。 6. 检查Docker环境(如果使用Docker编译) 如果是在Docker容器中编译,根据引用[2],Docker默认的TasksMax(任务数)限制可能会导致问题。可以设置TasksMax为无限: `sudo systemctl set-property docker.service TasksMax=infinity` 然后重新加载并重启docker。 7. 检查inotify限制(文件监控数) 编译过程中可能会用到inotify,可以通过以下命令查看当前限制: `cat /proc/sys/fs/inotify/max_user_watches` 如果值较小(如8192),可以增加: `echo 65536 | sudo tee /proc/sys/fs/inotify/max_user_watches` 8. 检查是否有僵尸进程或未关闭的文件 使用`ps aux`查看是否有大量僵尸进程,或者使用`lsof`查看是否有大量打开的文件未关闭。 9. 重启编译环境 有时候,简单地重启一下系统或者重新进入编译环境,可以释放一些资源。 由于Android编译是一个资源密集型任务,建议在开始编译前,先检查并调整这些限制。 注意:修改系统限制需要管理员权限,请谨慎操作。 下面给出一个具体的解决步骤示例: 步骤1:修改进程数和文件描述符限制 编辑/etc/security/limits.conf,添加: * soft nproc 20480 * hard nproc 40960 * soft nofile 8192 * hard nofile 65536 步骤2:修改系统进程数上限 编辑/etc/sysctl.conf,添加: kernel.pid_max = 65535 然后运行`sudo sysctl -p`生效。 步骤3:增加inotify限制 编辑/etc/sysctl.conf,添加: fs.inotify.max_user_watches = 65536 同样运行`sudo sysctl -p`生效。 步骤4:如果使用Docker,修改Docker服务配置(如引用[2]所述) sudo systemctl set-property docker.service TasksMax=infinity sudo systemctl daemon-reload sudo systemctl restart docker 步骤5:重新登录用户,使limits.conf生效(或者重启系统) 步骤6:在编译时,适当控制并行任务数,例如: make -j8 # 根据你的CPU核心数合理设置,一般不超过CPU核心数的2倍 如果问题仍然存在,可以尝试进一步增加这些限制,或者检查系统日志(/var/log/syslog)获取更多错误信息。 希望这些方法能帮助你解决编译错误。</think>### 解决 Android 编译错误:`FAILED: posix_spawn: Resource temporarily unavailable` 该错误通常由 **系统资源限制** 引起,尤其是在并行编译(如 `make -j`)时进程数或文件描述符超过限制。以下是系统级解决方案: --- #### **1. 增加用户进程数限制** ```bash # 查看当前限制 ulimit -u # 临时增加(仅当前会话有效) ulimit -u 8192 # 永久修改(需 root) echo "* soft nproc 16384" | sudo tee -a /etc/security/limits.conf echo "* hard nproc 32768" | sudo tee -a /etc/security/limits.conf ``` **说明**:Android 编译会启动大量子进程,默认限制(通常 1024)易被耗尽[^4]。 --- #### **2. 提升系统级进程上限** ```bash # 检查系统最大进程数 cat /proc/sys/kernel/pid_max # 永久修改(需 root) sudo sysctl -w kernel.pid_max=65535 echo "kernel.pid_max=65535" | sudo tee -a /etc/sysctl.conf ``` **原理**:系统总进程数上限需高于所有用户进程之和[^4]。 --- #### **3. 调整文件描述符限制** ```bash # 查看当前限制 ulimit -n # 永久修改(需 root) echo "* soft nofile 65536" | sudo tee -a /etc/security/limits.conf echo "* hard nofile 131072" | sudo tee -a /etc/security/limits.conf ``` **原因**:编译过程中频繁读写文件,需更多文件句柄[^5]。 --- #### **4. 减少并行编译任务数** 在编译命令中显式降低并行度: ```bash # 将 -j 后的数值改为 CPU 核心数的 1.5 倍(如 8 核改为 12) make -j12 # 替代 make -j$(nproc) ``` **注意**:过度并行(如 `make -j` 无参数)易触发资源竞争[^1]。 --- #### **5. 检查内存与交换空间** ```bash # 确保交换空间(Swap)足够(建议 ≥ 物理内存的 50%) free -h # 临时增加交换文件(示例增加 8GB) sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile ``` --- #### **6. 系统级深度排查** - **检查僵尸进程**:`ps aux | grep 'Z'` - **监控资源使用**: ```bash top -c # 按 CPU 排序 htop # 交互式资源监控 vmstat 2 # 每 2 秒输出系统状态 ``` --- #### **若在 Docker 中编译** 根据引用[^2]调整 Docker 服务配置: ```bash # 解除 Docker 任务数限制 sudo systemctl set-property docker.service TasksMax=infinity sudo systemctl daemon-reload sudo systemctl restart docker ``` --- ### 验证修复 1. 重新登录终端使配置生效 2. 执行编译前运行: ```bash ulimit -a # 确认 nproc/nofile 已提升 ``` 3. 重新编译观察错误是否消失 > **关键提示**:修改系统级限制需重启或重新登录生效。若问题持续,检查内核日志:`dmesg | grep -i "resource"`[^1][^4]。 --- ### 相关问题 1. 如何诊断 Linux 中 `Resource temporarily unavailable` 的具体原因? 2. Android 编译优化:如何平衡并行任务数与系统资源? 3. 除资源限制外,还有哪些常见原因会导致 `posix_spawn` 失败? 4. 如何在 Docker 容器中动态调整资源限制? [^1]: Linux 编程中 EAGAIN 错误的常见场景分析 [^2]: Docker 容器资源限制的调整方法 [^3]: POSIX 优先级限制与系统实现差异 [^4]: 进程数超限导致 fork 失败的解决方案 [^5]: Linux 资源限制调整的综合指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值