You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Windows下C文件复制程序的"copy: Bad file descriptor"错误?

Fixing the "Bad file descriptor" Error in Your Custom mycp Program

Let's walk through the issues in your code that are causing that frustrating error, plus fix other bits to meet your original requirements:

1. Operator Precedence Bug (Main Cause of the Error)

This is the root of your "Bad file descriptor" problem. Look at this line in your source file loop:

if (fds = _open(argv[i], _O_RDONLY) < 0)

The < operator has higher precedence than =, so this actually evaluates to:

fds = (_open(...) < 0)

That means fds gets assigned a boolean value (0 or 1) instead of the valid file descriptor from _open. When you try to read from this invalid descriptor, the error is thrown.

Fix: Wrap the assignment in parentheses to force the correct order:

if ((fds = _open(argv[i], _O_RDONLY)) < 0)

2. Reversed Parameters in copy_file Call

Your copy_file function expects the destination file descriptor first, then the source:

int copy_file(int fdd, int fds) { // fdd = destination, fds = source
    while ((n = read(fds, buf, BUFSIZE)) > 0) {
        _write(fdd, buf, n);
    }
}

But in your loop, you're passing the source first and destination second:

if (copy_file(fds, fdd) < 0)

This swaps your read/write targets, which would cause errors even if the descriptor was valid.

Fix: Swap the parameters in the call:

if (copy_file(fdd, fds) < 0)

3. Loop Starts at the Wrong Index

Your original loop starts at i=0, which points to argv[0]—the program's own executable (mycp.exe). You didn't intend to copy the executable itself, so this is a wasteful (and potentially confusing) mistake.

Fix: Start the loop at i=1, since source files begin at argv[1]:

for (i = 1; i < dest_idx; ++i) // dest_idx = argc - 1 (destination file index)

4. Incorrect Handling of Missing Source Files

Your requirement says if a source file doesn't exist, the program should print a warning and continue—not exit. Right now, any failed _open triggers an immediate exit.

Fix: Check the errno value when _open fails. If it's ENOENT (file not found), print a warning and skip to the next file. For other errors, exit as intended:

if ((fds = _open(argv[i], _O_RDONLY)) < 0) {
    if (errno == ENOENT) {
        fprintf(stderr, "Warning: File %s does not exist, skipping.\n", argv[i]);
        continue;
    } else {
        remove_dest_file(fdd, argv, dest_idx);
        exit_sys("open source file");
    }
}

5. Minor Polish & Robustness

  • Check _write return value: Your copy_file function didn't verify if writes succeeded. Add a check to catch write failures:
    while ((n = read(fds, buf, BUFSIZE)) > 0) {
        if (_write(fdd, buf, n) != n) {
            return -1; // Indicate write failure
        }
    }
    
  • Fix typo: printf("Succes"); → printf("Success!\n");
  • Clarify usage message: Update the error message to reflect correct syntax more clearly.

Fixed Full Code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

#define BUFSIZE 1024

void exit_sys(const char* msg) {
    perror(msg);
    exit(EXIT_FAILURE);
}

void exit_fail(const char* msg) {
    fprintf(stderr, "%s\n", msg);
    exit(EXIT_FAILURE);
}

void remove_dest_file(int fd, char** argv, int dest_idx) {
    _close(fd);
    unlink(argv[dest_idx]);
}

int copy_file(int fdd, int fds) {
    char buf[BUFSIZE];
    int n;
    while ((n = read(fds, buf, BUFSIZE)) > 0) {
        if (_write(fdd, buf, n) != n) {
            return -1;
        }
    }
    return n < 0 ? -1 : 0;
}

int main(int argc, char** argv) {
    int fds, fdd;
    int ch;
    int flags;
    int dest_idx;
    int i;

    flags = _O_WRONLY | _O_CREAT;
    if (argc < 3) {
        exit_fail("usage: mycp.exe source1.txt [source2.txt ...] dest.txt");
    }

    dest_idx = argc - 1;
    if (!access(argv[dest_idx], F_OK)) {
        printf("The file %s exists. Do you want to overwrite? [y/N]\n", argv[dest_idx]);
        ch = getchar();
        if (ch == 'y' || ch == 'Y') {
            flags |= _O_TRUNC;
        } else {
            exit(EXIT_SUCCESS);
        }
    }

    if ((fdd = _open(argv[dest_idx], flags, _S_IREAD | _S_IWRITE)) < 0) {
        exit_sys("open destination file");
    }

    for (i = 1; i < dest_idx; ++i) {
        if ((fds = _open(argv[i], _O_RDONLY)) < 0) {
            if (errno == ENOENT) {
                fprintf(stderr, "Warning: File %s not found, skipping.\n", argv[i]);
                continue;
            } else {
                remove_dest_file(fdd, argv, dest_idx);
                exit_sys("open source file");
            }
        }

        if (copy_file(fdd, fds) < 0) {
            remove_dest_file(fdd, argv, dest_idx);
            exit_sys("copy file");
        }

        _close(fds);
    }

    printf("Success!\n");
    _close(fdd);
    return 0;
}

内容的提问来源于stack exchange,提问作者user13575644

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 17:17:32