Ответы пользователя по тегу C
  • Как использовать libstdc на Bare Metal?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Есть по-разному устроенные libc, некоторые из них можно приспособить для работы в ядре. Для начала нужно понимать, что в libc есть часть, которая совсем не зависит от ОС (например все функции mem*() или большинство функций str*()), есть часть, зависимость которой от ОС реализована в терминах других функций libc (например printf() может выделять память и может записывать в файл, но обе эти функции уже реализованы в других местах libc), а есть часть напрямую взаимодействующая с ОС.
    Некоторые libc написаны так, что эта последняя часть чётко отделена (например newlib) и для адаптации к другой ОС или к окружению внутри ядра нужно реализовать небольшое количество интерфейсов (для newlib это будет вариант libgloss).
    Ответ написан
    Комментировать
  • Каким образом прерывания работают в esp8266?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Нашел документацию по ISA Xtensa

    Если вопрос действительно "каким образом прерывания работают", то isa book -- правильное место чтобы начать разбираться.

    В memory map esp8266 этот вектор заносится по адресу 0x40000050
    Не уверен, конечно, что это так


    Это так, можно посмотреть в конфигурационном оверлее.
    Ответ написан
  • Нету структуры file_operation, в хедере fs.h, как исправить? как установить полные хедеры ядра?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    изучаю разработку модулей ядра,попытался скомпилировать модуль использующий структуру file_operation - ошибка,как оказалось в моих хедерах ядра(/usr/include/linux/) нету данной структуры

    Хедеры ядра которые устанавливаются в системе -- это интерфейс между ядром и юзерспейсом (uapi). Хедер который тебе нужен -- внутренний хедер ядра. Чтобы собрать модуль ядра нужно иметь сконфигурированные исходники этого ядра. Почитать можно здесь.
    Ответ написан
    Комментировать
  • 2 переменные в одном адресе Си11 ARM STM32?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Может, дело в отладчике?

    Может и в отладчике. Поскольку обе переменные глобальные, то для проверки можно посмотреть в вывод readelf -a -- там должны быть их адреса. Или напечатать адреса из программы.
    Ответ написан
  • Почему функция неправильно изменяет динамический массив?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Можете подсказать причину?

    Неправильная работа с указателями. Конкретно:

    void test(char** array){
    	array = malloc(sizeof(char*));
    	array[0] = malloc(255 * sizeof(char));
    	strcpy(array[0], "Hello world!");
    }

    Если имелось в виду выделение и возврат массива строк, то должно быть так:
    void test(char*** array){
    	*array = malloc(sizeof(char*));
    	(*array)[0] = malloc(255 * sizeof(char));
    	strcpy((*array)[0], "Hello world!");
    }


    char** array;
    test(array);

    Здесь должно быть
    char** array;
    test(&array);
    Ответ написан
    3 комментария
  • Как в io_uring отправить sqe, чтобы sqe выполнилось через 3 секунды после io_uring_submit?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как выполнить задержку не понимаю

    Для организации таймаута в liburing есть io_uring_prep_timeout, но кроме этого нужно сериализовать таймаут и все предыдущие команды (чтобы таймаут начинался после их окончания) и следующую после таймаута команду и сам таймаут (чтобы последующие команды не стартовали вместе с таймаутом). Сериализация делается установкой флага IOSQE_IO_DRAIN для sqe, почитать об этом можно например здесь. У меня нарисовался следующий пример, который записывает в файл (stderr), делает паузу в одну секунду, а потом записывает ещё:
    #include <fcntl.h>
    #include <liburing.h>
    #include <stdio.h>
    #include <sys/mman.h>
    
    #define QUEUE_DEPTH 16
    
    int main(int argc, char **argv)
    {
            int i;
            struct io_uring ring;
            struct io_uring_cqe *pcqe;
            static const char msg0[] = "before timeout\n";
            static const char msg1[] = "after timeout\n";
            struct io_uring_sqe *sqe;
    
            io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
            io_uring_prep_write(io_uring_get_sqe(&ring), 2, msg0, sizeof(msg0), 0);
    
            sqe = io_uring_get_sqe(&ring);
            io_uring_prep_timeout(sqe, (struct __kernel_timespec[]){{.tv_sec = 1}},
                                  -1, IORING_TIMEOUT_ETIME_SUCCESS);
            io_uring_sqe_set_flags(sqe, IOSQE_IO_DRAIN);
    
            sqe = io_uring_get_sqe(&ring);
            io_uring_prep_write(sqe, 2, msg1, sizeof(msg1), 0);
            io_uring_sqe_set_flags(sqe, IOSQE_IO_DRAIN);
            io_uring_submit(&ring);
            for (i = 0; i < 3; ++i) {
                    int rv = io_uring_wait_cqe(&ring, &pcqe);
                    if (rv < 0) {
                            errno = -rv;
                            perror("io_uring_wait_cqe");
                    } else {
                            io_uring_cqe_seen(&ring, pcqe);
                    }
            }
    }
    Ответ написан
    Комментировать
  • Как из массива байтов HEX сделать сделать DEC?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как вернуть как было в новый массив

    byte summ[N];
    word s = x * y;
    
    for (i = 0; i < N; ++i) {
        summ[i] = s % 256;
        s /= 256;
    }
    Ответ написан
    2 комментария
  • Как устранить ошибку конверсии при использовании битовых полей?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как устранить ошибку конверсии при использовании битовых полей?

    Не использовать битовые поля. Серьёзно. Удобств на копейку а мороки на рубль.
    Ответ написан
    4 комментария
  • Почему передается некорректный адрес указателя в функцию?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Потому что переменная со спецификатором static локальна для единицы трансляции. Ты написал static button s1; в заголовочном файле, а это значит, что каждая единица трансляции в которую ты подключил этот файл получит свой собственный, независимый экземпляр переменной s1. Функция ModesInit инициализирует s1 из ModeDriver.o, а s1 из main.o останется неинициализированным.

    Исправить это можно заменив static на extern в заголовочном файле, а в одном из исходников добавив определение для переменной -- button s1;.
    Ответ написан
    1 комментарий
  • Компилятор выдаёт ошибку при попытке вызвать sizeof() относительно моего массива. Как исправить ошибку?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В C параметр функции не может быть массивом, только указателем. Синтаксис "имя с квадратными скобками" несёт тот же смысл, что и "имя со звёздочкой" когда речь идёт о параметрах функции. Если внутри функции взять sizeof от такого параметра результат будет равен sizeof от указателя. Это очень распространённая ошибка и компилятор говорит тебе об этом. Если тебе нужен размер массива переданного в функцию -- передавай его отдельно, например отдельным параметром.

    sizeof(dict)/sizeof(const char)

    Здесь ещё одна ошибка: dict -- это массив указателей (на самом деле указатель на такой массив, но по крайней мере, ты ожидал массив указателей), но ты делишь размер массива на размер const char а не на размер const char *. Во избежание таких ошибок для вычисления размера массива обычно пишут sizeof(dict)/sizeof(dict[0]).
    Ответ написан
    Комментировать
  • Контринтуитивный синтаксис объявления нескольких переменных одного типа?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    можно подумать, что при объявлении указателя, символ * относится к имени(не как часть, а как что-то зависящее от него), а не к типу.

    Если взять стандарт языка (например C99) и почитать главы Declarations, Type Specifiers и Declarators, то можно увидеть, что он разделяет declaration-specifiers, в который входят только слова и declarators, в который входят скобочки и звёздочки. Т.е. твой вывод по сути верный.

    Там же можно увидеть, что часть называемую declarator всегда можно обернуть в скобки, из чего можно извлечь следующий вывод: часть объявления вокруг которой можно поставить скобки самым широким образом относится к конкретному идентификатору, оставшаяся часть -- ко всему списку. Т.е. const char *a, b; можно превратить в const char (*a), b, но нельзя превратить в const (char *a), b или в char (const *a), b.

    Ну и напоследок стоит добавить, что такая интерпретация объявления не следует ни из чего с необходимостью, это просто решение которое было принято разработчиками языка. Они могли принять это решение по-другому и тогда уже другие конструкции вызывали бы наше удивление.
    Ответ написан
    2 комментария
  • Есть ли способ быстро выравнивать адреса?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    можно посчитать остаток от деления адреса на выравнивания, и затем прибавить его к адресу, но можно ли сделать это как-то быстрее? Например с помощью битовых операций.

    Можно, если выравнивание по степени двойки. addr = (addr + alignment - 1) & -alignment
    Ответ написан
  • Почему нет инфы о библиотеках в procfc файле maps, которые в сишном коде подключены и используются?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Компилирую gcc -o outfile source.c -lpthread. То есть собираю без всяких статиков, чтобы были зависимости к подключенным библиотекам. Далее запускаю процесс, чекаю /proc/pid/maps. Там нет ни единого упоминания к libpthread.

    100500 лет назад libpthread объединилась с glibc и теперь хоть и существует отдельно, чтобы программы использующие -lpthread продолжали собираться, внутри пустая. Короче, ты выбрал неудачного кандидата для экспериментов.
    Ответ написан
    Комментировать
  • Почему появляется ошибка make: *** [Makefile:15: leak] Ошибка 1 при выполнении Makefile на C?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    make: *** [Makefile:15: leak] Ошибка 1

    В linux это код ошибки "нет доступа". Начни с проверки что $(NAME) доступен для чтения и выполнения.
    Кроме того, для полноты картины стоит показывать полный лог выполнения команды make, а не только последнее сообщение об ошибке.
    Ответ написан
  • Почему в Си после main() не ставят ;?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему в Си после main() не ставят ;?

    в С при определении функции не ставят ; между объявлением и телом функции, не только для main, но и для любой другой функции. Согласно стандарту языка, например С99 приводит следующий синтаксис определения функции:
    function-definition:
        declaration-specifiers declarator declaration-list<opt> compound-statement
    declaration-list:
        declaration
        declaration-list declaration


    Этот синтаксис включает в себя также старый формат определения функции (без прототипа), в котором все аргументы должны быть объявлены между закрывающей круглой скобкой и открывающей фигурной, например (из того же стандарта):
    extern int max(a, b)
    int a, b;
    {
        return a > b ? a : b;
    }

    Однако, этот список должен содержать как минимум одно объявление и не может состоять из одной только ;.

    эта строка работает на другом языке?

    о каком "другом" языке речь?
    Ответ написан
    2 комментария
  • Как реализовать кроссплатформенную поддержку Unicode в аргументах командной строки в C?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Соответственно, мне нужно конвертировать массив wchar_t в массив char перед шифрованием, а после дешифровки выполнять обратную конвертацию.

    Этот вывод не следует из исходных данных. Массив данных любого типа может быть проинтерпретирован как массив байтов, без какой бы то ни было конверсии. Т.е. исходные данные в любом формате можно зашифровать, а потом расшифровать обратно. Поэтому имеет смысл отделить преобразование форматов входных данных от шифрования/расшифровки.

    Я поменял сигнатуру функции main() на int main(int argc, wchar_t* argv[]) (пытался исправлять на wmain, но тогда ругается ld и сборка падает с ошибкой).

    То, что ты меняешь прототип main, никак не влияет на то, как она будет реально вызвана. В стандарте языка C написано, каким может быть прототип main: int main(void), int main(int argc, char *argv[]) или эквивалентным. Там же написано, что набор символов во время выполнения программы -- implementation defined, поэтому нет гарантии, что их можно обработать кросплатформенно.

    Для конвертации wchar_t* в char* я пробовал использовать функцию wcstombs, однако почему-то у меня она совершенно не работает (при попытке преобразовать строку, содержащую только латиницу, я получаю null).

    wcstombs не занимается выделением памяти, если ты "получаешь null" -- это происходит в каком-то другом месте. Ну и если ты это делаешь внутри main принимающего wchar_t* argv[], то твой код интерпретирует строку char как строку wchar_t, что добавляет хаоса.
    Ответ написан
  • Скомпилированный в GCC exe файл вылетает досрочно?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Но в режиме отладки всё, как я уже писал выше, работает.

    Да не, это только видимость. Смотри:

    $ gcc -std=c99 -O2 -g3 -fsanitize=address main.c acp.c md5.c -o main
    $ ./main
    Base64('Hello') = "SGVsbG8="
    MD5('Hello') = "8b1a9953c4611296a827abf8c47804d7"
    =================================================================
    ==1045705==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x604000000071 at pc 0x7fb0d46486f8 bp 0x7ffd0affb580 sp 0x7ffd0affad30
    WRITE of size 33 at 0x604000000071 thread T0
        #0 0x7fb0d46486f7 in __interceptor_strcat ../../../../src/libsanitizer/asan/asan_interceptors.cpp:377
        #1 0x564b2388c0de in prepareKeys /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/acp.c:263
        #2 0x564b2388cac4 in acraw /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/acp.c:319
        #3 0x564b2388d8c2 in acraws /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/acp.c:401
        #4 0x564b2388d8c2 in acraws_basic /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/acp.c:409
        #5 0x564b2388a62e in testSimpleEncryption /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/main.c:20
        #6 0x564b2388a368 in main /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/main.c:111
        #7 0x7fb0d44461c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
        #8 0x7fb0d4446284 in __libc_start_main_impl ../csu/libc-start.c:360
        #9 0x564b2388a440 in _start (/home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/main+0x3440)
    
    0x604000000071 is located 0 bytes to the right of 33-byte region [0x604000000050,0x604000000071)
    allocated by thread T0 here:
        #0 0x7fb0d46b89cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
        #1 0x564b2388fee7 in md5StringHash /home/jcmvbkbc/tmp/toster/1331202/alphacrypt2/md5.c:227
    Ответ написан
  • Может ли язык Си работать на условной stack-based машине?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Может ли язык Си работать на условной стековой машине? … В виде стековой машины я имею в виду условную машину Тьюринга

    Есть такая штука, тезис Чёрча — Тьюринга, которая говорит, что любой алгоритм может быть реализован машиной Тьюринга.

    Будут ли какие-то проблемы для генерации кода из Си в ассемблер для подобной машины?

    Для этого надо уточнить, что такое "проблемы".
    Ответ написан
  • Что не так с Futex?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    почему такая ошибка со своим mutex

    потому что pthread_t шире чем int owner, и как следствие этот тест не работает.
    Ответ написан
  • Почему невозможно получить доступ к каталогу?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему ls не работает

    потому что main в процессе демонизации меняет текущий каталог на /. Если запускать его с полным путём (например ./main `pwd`/mntpoint) -- то становится лучше. Но всё ещё не работает, потому что при использовании обработчиком запроса на доступ к каталогу этого же самого каталога происходит бесконечная рекурсия и исходный запрос не завершается.
    Лучше спроси, как я это понял.
    Ответ написан