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

使用fdopen时出现Bad file descriptor错误的技术求助

Fixing "Bad file descriptor" Error with fdopen in Pipe/Fork Setup

Hey there! Let's figure out why you're hitting that "Bad file descriptor" error when using fdopen in your parent-child pipe setup. Your code is on the right track, but there are a few critical steps missing or misordered that are causing the issue. Let's break this down and fix it.

Common Causes of the Error

First, let's list the most likely culprits for this specific error in your pipe/fork scenario:

  • Closing the wrong pipe file descriptor in the child process (e.g., closing the read end instead of the write end)
  • Forgetting to close unused pipe ends in either parent or child (leads to invalid descriptor states)
  • Using the wrong mode with fdopen (e.g., trying to write to a pipe's read end)
  • Botching the STDIN redirection steps before executing test3

Corrected Full Code

Here's a complete, working version of your code with explanations for each key step:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>

int main(int argc, char *argv[]) {
    int fd[2];
    char buf[] = "HELLO WORLD!";

    // Create pipe - check for failure explicitly
    if (pipe(fd) == -1) {
        perror("pipe");
        return EXIT_FAILURE;
    }

    switch (fork()) {
        case -1:
            perror("fork");
            // Clean up open pipe fds on error to avoid leaks
            close(fd[0]);
            close(fd[1]);
            return EXIT_FAILURE;
        
        case 0: // Child process
            // Child doesn't need the pipe's write end - close it immediately
            close(fd[1]);

            // Option 1: Redirect STDIN to pipe read end, then exec test3
            // This is what you need to pass data to test3's STDIN
            if (dup2(fd[0], STDIN_FILENO) == -1) {
                perror("dup2");
                close(fd[0]);
                exit(EXIT_FAILURE);
            }
            // Now STDIN points to the pipe, close the original read fd
            close(fd[0]);

            // Execute test3 - this replaces the child process with test3
            execl("./test3", "test3", NULL);
            // If we reach here, execl failed
            perror("execl test3");
            exit(EXIT_FAILURE);

            // Option 2: If you wanted to read in the child directly with fdopen
            // (not needed if you're exec-ing test3)
            // FILE *pipe_in = fdopen(fd[0], "r");
            // if (!pipe_in) {
            //     perror("fdopen");
            //     close(fd[0]);
            //     exit(EXIT_FAILURE);
            // }
            // // Read from the pipe
            // char read_buf[100];
            // fgets(read_buf, sizeof(read_buf), pipe_in);
            // printf("Child read: %s\n", read_buf);
            // fclose(pipe_in);
            // exit(EXIT_SUCCESS);
        
        default: // Parent process
            // Parent doesn't need the pipe's read end - close it
            close(fd[0]);

            // Write data to the pipe
            ssize_t bytes_written = write(fd[1], buf, strlen(buf));
            if (bytes_written == -1) {
                perror("write");
            } else {
                printf("Parent wrote %zd bytes: %s\n", bytes_written, buf);
            }

            // Close write end to signal EOF to child
            close(fd[1]);

            // Wait for child to finish to avoid zombie processes
            wait(NULL);
            return EXIT_SUCCESS;
    }
}

Key Fixes Explained

  1. Proper Pipe End Management:

    • In the child, we close fd[1] (the write end) immediately because we only need to read from the pipe. If you accidentally closed fd[0] instead, fdopen would try to open a closed descriptor, causing the "Bad file descriptor" error.
    • In the parent, we close fd[0] (the read end) since we only need to write to the pipe. Leaving unused ends open can prevent EOF signals and cause unexpected blocking.
  2. STDIN Redirection for test3:

    • To get test3 to read from the pipe, we use dup2(fd[0], STDIN_FILENO) to replace the child's standard input with the pipe's read end. After this, we close the original fd[0] because it's no longer needed.
    • If you skip this step and try to use fdopen before exec-ing, test3 won't inherit that file pointer—exec replaces the entire process image, so you need to set up the file descriptors before calling execl.
  3. Error Handling & Cleanup:

    • We add explicit cleanup of pipe descriptors on fork/pipe failure to avoid file descriptor leaks.
    • We check the return value of dup2 and execl to catch errors early.
  4. fdopen Usage (If Needed):

    • If you weren't exec-ing test3 and wanted to read in the child directly, use fdopen(fd[0], "r")—make sure you're opening the read end with read mode. Using "w" here would cause the same "Bad file descriptor" error.

Final Checks

  • Ensure test3 is compiled and exists in the same directory (or use the full path in execl).
  • Verify that test3 reads from standard input (e.g., uses scanf, fgets, etc.).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:00:46