程序运行时被用户删除了工作目录后崩溃

最近遇到这样的问题,Android下运行程序Program,在程序初始化时会创建自己的工作目录,存放一些缓存、日志和配置文件。

而如果用户在此程序运行期间删除了它的工作目录,此程序会在下次用到该目录时,发现目录已经不可访问,然后重新创建目录,但是创建会失败,导致后续的崩溃。

而创建失败的原因是errno 16 : EBUSY (Device or resource busy), 意思是说当前目录已经被占用,不可以创建同名的目录覆盖它。

我很郁闷,原来的目录不是已经访问不到了(access()或File.exists()),为什么会出现这种问题呢?

问题解析:用户在删除目录之前,program程序中还有指向该目录中文件的文件指针没有关闭,也就是说程序还在引用该目录里文件,因此此目录是删除不了的。用户执行了删除操作后,即使看到文件管理器中没有了该目录,而实际上该目录还是存在的,操作系统是能够识别的。因此,下次程序需要访问目录时,发现该目录访问不了,因此它认为此目录不存在(实际上存在,只是不可访问了),因此想要创建新的同名目录,而操作系统发现这是要覆盖已有目录的操作,而已有目录正在被引用,不可覆盖,因此会报错。所以,program认为发生了目录创建失败,就会导致后续的失败。

总之,一句话,问题的原因是你删除了文件,而之前没有关闭掉文件

解决方法:在文件或目录删除前,保证所有的文件指针被关闭掉,即关闭所有对文件的引用。但是我怎么知道文件什么时候会被(手痒的用户)删除呢?

一种方式,就是每次操作文件,都要打开文件和关闭文件的操作,这样可以避免长期引用文件,极大减少了以上问题发生的概率。但是对于一些文件操作频繁的功能来说,每次都要打开文件是低效的,比如日志操作,经常要写日志文件。对于这种情况,长期持有文件指针是高效的,但是会遇到之前的问题。我的做法就是,每次访问文件指针之前,都要判断当前路径还是否完好,如果路径不存在了,那就关闭当前目录下所有的文件指针,这样能保证不再持有相关的文件引用,使得当前目录能被正常删除,然后重新创建目录,然后重新创建文件,并打开文件再次保存文件指针。

时间: 2024-10-10 08:34:33

程序运行时被用户删除了工作目录后崩溃的相关文章

程序运行时三种内存分配策略

按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的. 静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求. 栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对数据区的需求在编译时是完全未

VC项目程序运行时设置指定目录读取Dll

方法一: 选择当前工程,右击"Properties" -> "Configuration Properties" -> "Debugging",在"Working Directory"设置dll的路径就可以了 方法二:设置项目的环境变量 方法三: CString strDllPath = GetExePath() + _T("System"); SetDllDirectory(strDllPat

Java程序运行时的几个区域

Java运行时涉及到的区域 几个基本概念: 1.Java对象     2.Java方法    3.一个编译好的类,以class文件的形式出现 4.Java的本地方法   5.线程私有和线程共有 一.方法区(永久代) 和 堆(heap) 这两个区域是线程共有的,供所有线程使用.所以,对存放在这两个地方的资源进行操作时,如果是程序是多线程的,那么要考虑同步. 方法区存放的是类的类型信息.类的类型信息有,类的静态变量,其它从class文件中读取到的信息. 当用户访问一个类的静态方法或者类的静态变量,或

获取java程序运行时内存信息

由于最近想自己动手测试一下String和StringBuffer的效率问题,需要获取程序运行时的内存占中信息,于是上网查了一下,根据查到的资料写了个程序,发现结果有问题,才发现查到的资料是错误的.所以在这里跟大家分享一下获取内存占用的正确方法 错误的方法 //程序开始时:(先调用一下垃圾回收,但是不一定立即执行) Runtime.getRuntime().gc(); long initm=Runtime.getRuntime().freeMemory(); //程序结束时: Runtime.ge

C# 获取程序运行时路径

?  前言 开发中,很多时候都需要获取程序运行时路径,比如:反射.文件操作等..NET Framework 已经封装了这些功能,可以很方便的使用. 1.   可使用类 1.   System.AppDomain,程序集:mscorlib.dll. 2.   System.Environment,程序集:mscorlib.dll. 3.   System.IO.Directory,程序集:mscorlib.dll. 4.   System.Reflection.Assembly,程序集:mscor

Linux下程序运行时内存状态及相应查看工具

最近在解决一个编译问题时,一直在考虑一个问题,那就是Linux下可执行程序运行时内存是什么状态,是按照什么方式分配内存并运行的.查看了一下资料,就此总结一下,众所周知,linux下内存管理是通过虚存管理的,在分配内存是并非在物理内存开辟了一段空间,而是在使用时才分配的,而且是通过段页式管理.以上比较废话,开始看看程序运行时内存会是什么状态. 在linux下内存分配是以页为单位的,而页是通过段管理,各个段之间是独立的,方便管理.linux程序运行时,可以分为以下几个内存段: 一.BSS段 (bss

c/c++编译时,指定程序运行时查找的动态链接库路径

http://blog.csdn.net/tsxw24/article/details/10220735 c/c++编译时,指定程序运行时查找的动态链接库路径 分类: c/c++ linux 2013-08-23 14:04 1117人阅读 评论(0) 收藏 举报 [plain] view plaincopy $ g++ -Wl,-rpath,/usr/local/lib/ -oevh libevent_http.cpp -levent -Wl,-rpath,  用于指定程序运行时查找动态链接库

Android程序运行时权限与文件系统权限的区别

apk程序是运行在虚拟机上的,对应的是Android独特的权限机制,只有体现到文件系统上时才使用linux的权限设置. (1)Android中的apk必须签名 (2)基于UserID的进程级别的安全机制  (3)默认apk生成的数据对外是不可见的  (4)AndroidManifest.xml中的显式权限声明  Android程序运行时权限与文件系统权限的区别

程序运行时内存管理

1,管理运行阶段内存空间分配 malloc()/new; int *pn = new int(存储的类型,内存根据此设定相应存储字节的内存) pn是内存地址(所以 当声明一个变量的指针变量时没初始化,声明后再来初始化则pn 接收的应该是变量在内存中的地址 &VariableName); *pn是存储在内存的值 用于给所指向内存中的变量赋值; 为一个数据对象(结构,基本类型)获得并指定分配内存格式 typeName pointer_name = new typeName; 指定需要什么样的内存和用