Программа C отлично выводит на стандартный вывод в Linux, но ничего не выводит в Windows

Я написал пару программ, позволяющих кому-либо отправлять произвольные двоичные файлы в определенном радиорежиме с ограниченным набором символов, где каждый символ представлен некоторым кодом Хаффмана. Одна программа — кодировщик, другая — декодер.

Программы прекрасно работают в Linux. Он работает исключительно через стандартный ввод и вывод. Я фаззил их, используя случайные файлы размером 1 ГиБ. Однако когда я пытаюсь скомпилировать его для Windows (используя cl.exe или x86_64-w64-mingw32-gcc (в WSL), программы отказываются выводить что-либо в любой выходной поток.

Я пытался удалить все выходные данные в stderr, пытался выполнить два вызова putchar() с помощью '\r''\n' (думая, что это проблема с LF и CRLF), fflush() каждый раз, когда я putchar(), но это все равно не сработает. Единственное, что сработало, — это полностью закомментировать основной while цикл программы-кодировщика, в котором мне удалось получить исходную напечатанную строку FILE:.

Поскольку цикл не закомментирован, я даже не получу первый printf() с немедленным fflush(stdout) после него. Однако программа будет остановлена. Ниже представлена ​​одна из программ, которую я хочу отладить в первую очередь.

Для проверки работоспособности я попытался скомпилировать простую программу Hello World!, которая использует и printf(), и putchar(), и она отлично работает в Windows, но моя конкретная программа - нет. Я в растерянности, где проверить в первую очередь.

js8file_enc.c

#include "js8file_enc.h"

// From stdin
bool fill_buffer(bool * bitbuf, size_t * buf_size, bool ** bitbuf_read_head_ptr){
    // Justify remaining buffer back to the beginning
    if (*buf_size > 0){
        memmove(bitbuf, *bitbuf_read_head_ptr, *buf_size);
    }
    // Read from stdin (indeterminate length), keep track of buffer size
    char buf[BUF_SIZE];
    // The max bytes here is sizeof(buf) - ceil(*buf_size/8) expressed in a roundabout way.
    // This will fill our byte buffer as much as possible for the bit buffer to be near-full in the next step.
    size_t increase = fread(buf, 1, sizeof(buf) - ((*buf_size+8-1)/8), stdin);
    // Extract bits from byte buffer
    for(size_t i = 0; i < increase; i++){
        for(int j = 0; j < 8; j++){
            bitbuf[*buf_size] = (buf[i] >> (7 - j)) & 1;
            (*buf_size)++;
        }
    }
    *bitbuf_read_head_ptr = bitbuf;
    return increase > 0;
}

int main(){
    printf("FILE:");
    bool bitbuf[BUF_SIZE*8];
    bool * bitbuf_read_head = bitbuf;
    size_t buf_size = 0; // In bits
    while(true){
        if (buf_size < 8){ // 8 bits, length of longest key
            if (!fill_buffer(bitbuf, &buf_size, &bitbuf_read_head)){
                // There may still be bits remaining (<8), encode the rest
                while(buf_size > 0){
                    for(int i = buf_size; i > 0; i--){
                        if (LUT[i] == NULL){
                            continue;
                        }
                        uint8_t key = 0;
                        for(int j = 0; j < i; j++){
                            key |= bitbuf_read_head[j] << (i - j - 1);
                        }
                        if (LUT[i][key] != 0){
                            putchar(LUT[i][key]);
                            bitbuf_read_head += i;
                            buf_size -= i;
                            break;
                        }
                    }
                }
                break;
            }
        }
        int max_key_size = (buf_size < 8) ? buf_size : 8;
        // Produce keys in descending order, check for first match, write to stdout, then move buffer head.
        // If there are no codewords of length n (that is, LUT[n] is NULL), then we skip to the next length.
        for(int i = max_key_size; i > 0; i--){
            if (LUT[i] == NULL){
                continue;
            }
            uint8_t key = 0;
            for(int j = 0; j < i; j++){
                key |= bitbuf_read_head[j] << (i - j - 1);
            }
            if (LUT[i][key] != 0){
                putchar(LUT[i][key]);
                bitbuf_read_head += i;
                buf_size -= i;
                break;
            }
        }
    }
    fflush(stdout);
    fprintf(stderr, "<EOF>\n");
    fflush(stderr);
    return 0;
}

js8file_enc.h

#include "ref.h"

// Indexed by codeword length (.bits)
const unsigned char * LUT[9] = {
    [0] = NULL,
    [1] = (unsigned char[0b10]){
        [0b0] = ' ',
        [0b1] = 'E'
    },
    [2] = NULL,
    [3] = NULL,
    [4] = (unsigned char[0b10000]){
        [0b1101] = 'T',
        [0b0011] = 'A'
    },
    [5] = (unsigned char[0b100000]){
        [0b11111] = 'O',
        [0b11100] = 'I',
        [0b10111] = 'N',
        [0b10100] = 'S',
        [0b00011] = 'H',
        [0b00000] = 'R'
    },
    [6] = (unsigned char[0b1000000]){
        [0b111011] = 'D',
        [0b110011] = 'L',
        [0b110001] = 'C',
        [0b101101] = 'U',
        [0b101011] = 'M',
        [0b001011] = 'W',
        [0b001001] = 'F',
        [0b000101] = 'G',
        [0b000011] = 'Y'
    },
    [7] = (unsigned char[0b10000000]){
        [0b1111011] = 'P',
        [0b1111001] = 'B',
        [0b1110100] = '.',
        [0b1100101] = 'V',
        [0b1100100] = 'K',
        [0b1100001] = '-',
        [0b1100000] = '+',
        [0b1011001] = '?',
        [0b1011000] = '!',
        [0b1010101] = '"',
        [0b1010100] = 'X',
        [0b0010101] = '0',
        [0b0010100] = 'J',
        [0b0010001] = '1',
        [0b0010000] = 'Q',
        [0b0001001] = '2',
        [0b0001000] = 'Z',
        [0b0000101] = '3',
        [0b0000100] = '5'
    },
    [8] = (unsigned char[0b100000000]){
        [0b11110101] = '4',
        [0b11110100] = '9',
        [0b11110001] = '8',
        [0b11110000] = '6',
        [0b11101011] = '7',
        [0b11101010] = '/'
    }
};

ссылка.h

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
// DEFAULT SETTING: 524288
// 512 KiB, packed (bytes read from stdin)
// 4 MiB, unpacked (512 KiB worth of bits stored in bitbuf)
// Changed for debugging purposes
#define BUF_SIZE 524288

typedef const struct codeword{
    const uint8_t key;
    const uint8_t bits;
} codeword;

Обновлено: В первом ответе говорится, что размер стека Windows по умолчанию составляет 1 МБ. Я этого не знал, и я проверю это исправление.

warning C4013: '__builtin_expect' undefined; assuming extern returning int - Как вам вообще удалось связать его в Windows с помощью cl.exe, учитывая, что __builtin_expect не существует в cl.exe (цепочка инструментов Visual Studio)?
selbie 04.09.2024 22:10

@selbie Я понимаю, что я добавил это для Linux, а не для Windows, так как застрял в этой проблеме. Проблема возникает, если вы удалите все подсказки, но скомпилируете. Я обновлю вопрос.

Expectator 04.09.2024 22:13

Код довольно загадочный. Пожалуйста, сократите его до минимально воспроизводимого примера.

Eugene Sh. 04.09.2024 22:23
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эта строка в main():

bool bitbuf[BUF_SIZE * 8];

Где BUF_SIZE определяется в ref.h как 524288. При запуске из стека будет выделено 4 мегабайта. Это приведет к сбою вашей программы еще до того, как она доберется до оператора printf("FILE:").

По умолчанию компилятор VC допускает размер стека только 1 МБ.

Решения:

  • Измените приведенную выше строку следующим образом:

    bool* bitbuf = malloc(BUF_SIZE*8);

    (Не забудьте поставить free, когда закончите)

ИЛИ

  • Используйте флаги компилятора и компоновщика для увеличения размера стека (я могу поискать это, если хотите), но приведенное выше решение с использованием динамического распределения памяти лучше.

Аналогично, char buf[BUF_SIZE]; в fill_buffer занимает 512 КБ стека.

Технически вызов malloc() должен быть: bool* bitbuf = malloc((BUF_SIZE*8) * sizeof(bool)); поскольку sizeof(bool) не гарантированно будет 1 байт: В C сколько места занимает логическое значение (логическое значение)? Это 1 бит, 1 байт или что-то еще?

Remy Lebeau 04.09.2024 22:52

Обратите внимание, что большинство современных Unix-подобных систем по умолчанию предоставляют 8 МБ стека, поэтому реализация Linux работает нормально.

Jonathan Leffler 05.09.2024 04:25

Другие вопросы по теме