代码之家  ›  专栏  ›  技术社区  ›  Mauricio

stdio的remove()不总是按时删除

  •  2
  • Mauricio  · 技术社区  · 16 年前

    对于一个特定的作业,我正在使用标准C下的顺序文件实现一个基本的数据存储系统,一次不能加载多个记录。所以,基本的部分是创建一个新的文件,在这个文件中存储我们对原始记录所做的任何操作的结果。上一个文件已重命名,并在工作名称下创建一个新文件。代码是用Windows7上的mingw 5.1.6编译的。

    问题是,这个特定版本的代码(我的函数中有几乎相同的浮动版本)并不总是删除旧文件,因此重命名失败,因此存储的数据会被fopen()擦除。

    FILE *archivo, *antiguo;
    
    remove("IndiceNecesidades.old");  // This randomly fails to work in time.
    rename("IndiceNecesidades.dat", "IndiceNecesidades.old"); // So rename() fails.
    
    antiguo = fopen("IndiceNecesidades.old", "rb");
    // But apparently it still gets deleted, since this turns out null (and I never find the .old in my working folder after the program's done).
    archivo = fopen("IndiceNecesidades.dat", "wb"); // And here the data gets wiped.
    

    基本上,只要.old以前存在,就有可能没有及时删除它,以便rename()成功生效。内部和外部没有可能的名称冲突。

    奇怪的是只有这个文件。除了名称改为necesidades.dat(发生在3个不同的函数中)之外,相同的代码段工作得非常好。

    // I'm yet to see this snippet fail.
    FILE *antiguo, *archivo;
    
    remove("Necesidades.old");
    rename("Necesidades.dat", "Necesidades.old");
    
    antiguo = fopen("Necesidades.old", "rb");
    archivo = fopen("Necesidades.dat", "wb");
    

    关于为什么会发生这种情况,和/或我如何确保remove()命令在rename()执行时生效?(我想到只要fopen()返回一个非空指针,就用while循环再次强制调用remove(),但这听起来像是在乞求一个崩溃,因为用delete请求或其他东西溢出操作系统。)

    3 回复  |  直到 11 年前
        1
  •  3
  •   Mauricio    16 年前

    所以突然,在阅读了斯科特提到的权限之后,我想到了“被拒绝的权限”,并应用了一些谷歌。 Turned out it's a pretty common, if obscure, error. 卡夫是对的,这是另一段代码。也就是说,我忘记了在函数中fclose这个用来显示内容的文件。因为我没有跟踪那个特定的细节,所以看起来是随机的。

    免责声明:每周的数学辅导只需要很少的睡眠时间。第二章

        2
  •  1
  •   caf    16 年前

    这听起来很奇怪,甚至更奇怪的是,当您说相同的代码在不同的文件名下工作正常时——我强烈怀疑您的代码中的其他地方有一个bug。但是,您应该能够通过重命名要删除的文件来解决此问题:

    rename("IndiceNecesidades.old", "IndiceNecesidades.older");
    remove("IndiceNecesidades.older");
    rename("IndiceNecesidades.dat", "IndiceNecesidades.old");
    
        3
  •  1
  •   Scott Wales    16 年前

    最好检查一下 remove() 用于错误的函数。 man remove 表示函数返回 0 论成功与否 -1 失败时,设置 errno 记录错误。尝试将呼叫替换为

    if (remove("IndiceNecesidades.old") != 0){
       perror("remove(\"IndiceNecesidades.old\") failed");
    }
    

    它会给出一条错误消息,说明什么失败了。

    此外,似乎不需要删除

    人名词()

    rename()系统调用导致 名为“旧”的链接将重命名为“新”。 如果存在新的,则首先将其删除。 新旧必须相同 类型(即,两者都必须是 目录或非目录)和 必须驻留在同一文件系统上。

    rename()系统调用保证 一个新的实例总是 存在,即使系统应该崩溃 在手术过程中。

    如果旧的最后一部分是 符号链接,符号链接是 已重命名,而不是将文件或目录重命名为 它指出。

    如果出现以下情况,将返回EPERM:

    [eperm]目录 包含旧的标记为粘性,并且 包含目录和 旧的属于有效用户 身份证件。

    [eperm]新文件 存在,目录包含新的 标记为粘性,并且 拥有包含目录或新目录 通过EffEC - 有效的用户ID。

    下一步是检查您对包含目录的权限

    推荐文章