Получил разные типы ошибок в одной программе C в Linux

Я работаю над встроенным Linux (ядро-5.10.24) и теперь запускаю программу на C для стресс-тестирования копирования файлов. Код использует stdio для чтения и записи файла следующим образом:

#include <stdio.h>
#include <stdlib.h> // For exit()
#include <unistd.h>
#include <string.h>

#ifndef BUF_SIZE        /* Allow "cc -D" to override definition */
#define BUF_SIZE 1024
#endif

static unsigned char buf[BUF_SIZE];
static char *infname = "/tmp/src_file.bin";
static char *ofname  = "/tmp/dst_file.bin";

static int create_dest_file(const char *fname)
{
    FILE *fp = fopen(fname, "w");
    if (fp == NULL) {
        printf("Failed to create/truncate %s\n", fname);
        return 1;
    }
    fclose(fp);
    return 0;
}

static int copy_file(const char *src, const char *dest)
{
    FILE *fp, *fp2;
    int rlen = 0, wlen = 0, rc = 0;

    // Open one file for reading
    fp = fopen(src, "r");
    if (fp == NULL)
    {
        printf("Cannot open file %s\n", src);
        return 1;
    }

    fp2 = fopen(dest, "ab");
    if (fp2 == NULL) {
        fclose(fp);
        return 1;
    }

    while (1) {
        rlen = fread(buf, 1, sizeof(buf), fp);
        if (rlen > 0) {
            wlen = fwrite(buf, 1, rlen, fp2);
            if (wlen != rlen) {
                printf("Wrote len: %d, read len: %d\n", wlen, rlen);
                rc = 1;
                break;
            }
        } else {
            break;
        }
    }
    fclose(fp);
    fclose(fp2);
    return rc;
}

int main(int argc, char **argv)
{
    int i = 0, rc = 0;
    int us = 500000;

    if (argc != 4) {
        printf("Usage: %s srcfile dstfile delay_in_us\n", argv[0]);
        return 1;
    }

    infname = argv[1];
    ofname  = argv[2];
    us = atoi(argv[3]);

    printf("Copying %s to %s\n", infname, ofname);
    for (i = 0; i < 1000; i++) {
        create_dest_file(ofname);
        rc = copy_file(infname, ofname);
        printf("XXXXXXXXXXX %d, rc: %d\n", i, rc);
        usleep(us);
    }

    return 0;
}

После компиляции и запуска с помощью ./filecopy /root/16MB_src.bin /root/dest.bin 250000 я получал несколько разных типов ошибок, таких как Segmentation fault, Bus error, Illegal instruction и так далее.

Я установил GDB для запуска filecopy и получил следующую ошибку.

XXXXXXXXXXX 45, rc: 0
XXXXXXXXXXX 46, rc: 0
Fatal error: glibc detected an invalid stdio handle

Program received signal SIGABRT, Aborted.
0x77cdfd44 in ?? () from /lib/libc.so.6
(gdb) bt
#0  0x77cdfd44 in ?? () from /lib/libc.so.6
#1  0x77c964ac in raise () from /lib/libc.so.6
#2  0x77c97ae4 in abort () from /lib/libc.so.6
warning: GDB can't find the start of the function at 0x77cd0c97.
#3  0x77cd0c98 in ?? () from /lib/libc.so.6
(gdb)

Я проверил код и попросил других коллег просмотреть код, ошибок не обнаружено :-(.

Судя по типам ошибок, код вызывал одни и те же случайные сбои, но я не могу найти основную причину.

Система имеет 64 МБ ОЗУ, размер исходного файла составляет около 18 МБ, библиотека libc — GLIBC2.38.

Многие тесты показали, что если размер исходного файла составляет около 1 МБ, программа работает хорошо, ошибок не возникает.

Если исходный файл около 8 МБ и 18 МБ, программа выдаёт ошибки.
Если файл (18 МБ) читается из NAND и записывается в ОЗУ, значит, все прошло хорошо. Если файл (18 МБ) читается из ОЗУ и записывается в NAND, возникает ошибка.

Результат free -k показал

# free -k
              total        used        free      shared  buff/cache   available
Mem:          54580       13228        9404         344       31948       38260
Swap:             0           0           0

# free -k
              total        used        free      shared  buff/cache   available
Mem:          54580       13252       17480         344       23848       38240
Swap:             0           0           0

# free -k
              total        used        free      shared  buff/cache   available
Mem:          54580       13260       11936         344       29384       38232
Swap:             0           0           0

# free -k
              total        used        free      shared  buff/cache   available
Mem:          54580       13252        6656         344       34672       38240
Swap:             0           0           0

# free -k
              total        used        free      shared  buff/cache   available
Mem:          54580       13244       19304         344       22032       38224

Память НЕ израсходована.

🤔 А знаете ли вы, что...
C оставляет множество возможностей для оптимизации кода и достижения высокой производительности приложений.


85
1

Ответ:

Решено

Кажется, с вашей программой все в порядке, ваша проблема, скорее всего, кроется в другом.

Я получал несколько различных типов ошибок, таких как ошибка сегментации, ошибка шины, недопустимая инструкция и так далее.

Все это может быть результатом плохой памяти (чтение значений, отличных от записанных ранее).

Я предлагаю запустить программу проверки памяти, чтобы подтвердить или исключить эту возможность.

Вы также можете запустить другие известные стабильные приложения, интенсивно использующие память (например, сам gcc) — если вы также видите сбои в них, весьма вероятной основной причиной является «плохая память».