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

fread()读取部分HTML文件报错(errno=14) 如何修复?

fread() returns "Bad Address" (errno 14) when reading specific files in C

I'm trying to read files using the following C code:

Main code snippet:

#define RESPONSE_MAX_LENGTH (1024 * 1024) // Should be 1MB
char file_content[RESPONSE_MAX_LEGNTH];
memset(&file_content, 0, RESPONSE_MAX_LEGNTH);
request_get_file("/User/...", file_content);

Function declaration:

int request_get_file(char* requested_file_path, char* buf) {
    int file_size = 0;
    FILE* fp = NULL;
    if ((fp = fopen(requested_file_path, "r+")) == NULL) {
        return errno;
    }
    fseek(fp, 0L, SEEK_END);
    file_size = (int)ftell(fp);
    rewind(fp);
    errno = 0;
    if (fread(buf, 1, file_size, fp) == 0) {
        if (!feof(fp)) {
            if (ferror(fp)) {
                printf("An error occured while reading the requested file. File size: %d\n", file_size);
                perror("fread()");
                return errno;
            }
        }
    }
    fclose(fp);
}

This code works fine for .txt files, but when reading some HTML files, I get the error message: fread(): Bad address (via perror("fread()")), with errno = 14. The error only happens with specific files. Later I renamed the problematic test.html to test.txt and the error still occurred, so I confirmed it's caused by the buffer being too small. How can I fix this?


Great catch identifying the buffer size as the root cause! Let's break down the fixes step by step, including some hidden issues in your code that might be exacerbating the problem:

1. Fix the critical typo first

Look closely at your macro and variable: you defined RESPONSE_MAX_LENGTH but used RESPONSE_MAX_LEGNTH (note the missing 'L' in "LENGTH"). This typo means your buffer is being sized to an undefined macro value, which the compiler will treat as 0 (or a garbage value depending on settings). That's a direct cause of the "Bad Address" error, since you're trying to write to a buffer of invalid size.

2. Replace static buffer with dynamic allocation

A 1MB static array on the stack can cause stack overflow in some environments, and it's inflexible for files larger than 1MB. Instead, allocate memory dynamically based on the actual file size:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int request_get_file(char* requested_file_path, char** buf) {
    long file_size = 0; // Use long to handle files larger than 2GB (32-bit int limit)
    FILE* fp = NULL;

    // Open file in read-only mode (no need for "r+" since we're only reading)
    if ((fp = fopen(requested_file_path, "r")) == NULL) {
        perror("fopen()");
        return errno;
    }

    // Get file size, handle potential fseek/ftell failures
    if (fseek(fp, 0L, SEEK_END) != 0) {
        perror("fseek()");
        fclose(fp);
        return errno;
    }
    file_size = ftell(fp);
    if (file_size == -1) {
        perror("ftell()");
        fclose(fp);
        return errno;
    }
    rewind(fp);

    // Allocate buffer dynamically (+1 for null terminator if using as a string)
    *buf = malloc(file_size + 1);
    if (*buf == NULL) {
        perror("malloc()");
        fclose(fp);
        return ENOMEM;
    }
    memset(*buf, 0, file_size + 1);

    // Read file and verify all bytes were read
    size_t bytes_read = fread(*buf, 1, file_size, fp);
    if (bytes_read != file_size) {
        if (ferror(fp)) {
            printf("Failed to read file. Expected %ld bytes, read %zu bytes\n", file_size, bytes_read);
            perror("fread()");
            free(*buf);
            *buf = NULL;
            fclose(fp);
            return errno;
        }
    }

    fclose(fp);
    return file_size; // Return actual file size on success
}

3. Update your main code to use dynamic allocation

int main() {
    char* file_content = NULL;
    int result = request_get_file("/User/...", &file_content);

    if (result > 0) {
        // Use file_content here (e.g., print, parse, etc.)
        printf("Successfully read %d bytes of file content\n", result);
    } else {
        printf("Error reading file: error code %d\n", result);
    }

    // Don't forget to free the allocated buffer to avoid memory leaks
    if (file_content != NULL) {
        free(file_content);
    }
    return 0;
}

4. Additional key improvements

  • Use long for file size: int has a maximum limit (usually 2GB on 32-bit systems), so long lets you handle larger files without overflow.
  • Read-only file access: Using "r" instead of "r+" is safer and more efficient since you don't need write permissions for reading.
  • Full error checking: Your original code didn't handle failures from fseek or ftell, which could lead to incorrect file size calculations.
  • Null terminator support: Allocating an extra byte and zeroing it ensures you can safely use string functions (like strlen, printf) on the buffer if it contains text content.

Why you saw "Bad Address"

The error errno=14 corresponds to EFAULT, meaning the kernel detected an invalid memory address being accessed. In your case:

  1. The typo made your static buffer size invalid (likely 0), so fread tried to write to memory outside the valid buffer range.
  2. Even without the typo, if the file exceeded your 1MB static buffer, fread would write past the end of the array, triggering an access violation.

By switching to dynamic allocation, you ensure the buffer is always exactly the right size for the file, eliminating this error entirely.


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:41:09