Задать вопрос
  • GAS ассемблер: записать в секцию опкоды, затем выполнить их?

    includedlibrary
    @includedlibrary
    Да, можно. Вам надо найти заголовок программы PHDR, в котором располагается секция .text, и установить ему права на запись. Можно этого же добиться при линковке, с помощью скрипта компановщика:

    PHDRS {
        text PT_LOAD FLAGS(0x7);
    }
    
    SECTIONS {
        .text ALIGN (0x1000) : {
            *(.text)
        } :text
    }


    Так же можно добиться того же при помощи системного вызова mprotect из уже запущенной программы
    Ответ написан
    Комментировать
  • Необходима ли виртуальная страничная адресация в 4Гбайта при наличии ОЗУ емкостью 4Гбайта и почему?

    includedlibrary
    @includedlibrary
    Виртуальные адреса используются вне зависимости от объёма памяти, они используются для нескольких целей:
    1. Защита памяти одного приложения от вмешательства другого. Так как у каждого процесса своё виртуальное адресное пространство, процессы могут читать/писать только в память, которая была выделена им ОС.
    2. Для защиты памяти, используемой ОС, от пользовательских процессов. Работает аналогично первому пункту.
    3. Запуск программ, размер которых больше, чем доступный объём памяти. Мы можем грузить в память не все страницы программы, а когда исполнение доходит до отсутствующих, процессор выбрасывает исключение page fault, в таком случае часть ранее загруженных страниц можно выгрузить из памяти и загрузить новые по нужному виртуальному адресу.
    4. Также виртуальная адресация позволяет процессу использовать почти всё доступное адресное пространство. Так как страницы операционной системы отображаются в адресное пространство каждого процесса (для выполнения системных вызовов, обработки прерывний и т.п.), можно использовать для ОС очень близкие к концу виртуального пространства адреса, в таком случае остальные адреса будут доступны процессу. Например процессоры архитектуры x86-64 могут использовать до 2^48 или 2^52 байт памяти. Если поместить ядро, например в последние два гигабайта, то любому процессу будут доступны первые 2^48 - 2ГБ адресов, что более чем достаточно
    Ответ написан
    2 комментария
  • Ошибки в функции создания двумерного динамического массива С++. Как исправить?

    includedlibrary
    @includedlibrary
    Понимаю, что легче было бы это сделать через тот же тип double, но мне уже интересно, возможно ли это через void?


    Звучит как: "Понимаю, что проще поглощать пищу через рот, но уже интересно, возможно ли через заднее отверстие".

    Что мешает сразу сделать нормально и вернуть значение из функции:
    double** Array(unsigned int rows, unsigned int colms)
    {
        double** array2d = new double* [rows];
        for (unsigned int i = 0; i < rows; i++)
            array2d[i] = new double[colms];
        return array2d;
    }
    Ответ написан
    Комментировать
  • Для чего тесты пишут?

    includedlibrary
    @includedlibrary
    Тесты пишут, чтобы при изменениях в коде их прогонять и проверять, что определённое в тестах поведение не ломается. Да, можно каждый раз всё вручную прогонять, но вот для примера, у нас в проекте тысячи две автотестов, каждый раз всё это вручную прогонять ни у кого возможности нет
    Ответ написан
  • Как сделать одномерный массив в си?

    includedlibrary
    @includedlibrary
    Либо заранее просить пользователя ввести размер и использовать for:
    int size;
    scanf("%d", &size);
    int *list = malloc(sizeof(int) * size);
    for(int i = 0; i < size; i++)
        scanf("%d", &list[i]);


    Либо как сделали вы.

    Такой код, кстати, list[size++] = n; в какой-то момент приведёт к segfaul, потому что list, очевидно, фиксированного размера, а работа предполагается с массивом переменной длины. Почитайте про malloc/realloc
    Ответ написан
    Комментировать
  • Как использовать libstdc на Bare Metal?

    includedlibrary
    @includedlibrary
    Как верно заметили выше, никак. Но вообще, в ядре можно свои аналогичные функции написать, правда, они не всегда будут иметь тот же интерфейс, что и функции из стандартной библиотеки.
    Ответ написан
    4 комментария
  • Как корректно передать данные из std.ArrayList в Slice?

    includedlibrary
    @includedlibrary
    Ну, как минимум, вы неправильно считываете строки.
    while (reader.streamUntilDelimiter(line.writer(), '\n', null)) : (line_no += 1) {
            defer line.clearRetainingCapacity(); // по выходу из цикла буфер будет освобождён
            ...
            // тут вы для нескольких строк используете один и тот же буфер
           // даже если не освобождать память, у всех 26 структур будет указатель на один и тот же буфер, но
          // с разными смещениями
            statements[line_no] = .{ .content = line.items[(i + 1)..] };
    }
    Ответ написан
    Комментировать
  • Как создать правило make для компиляции списка .c в список .out?

    includedlibrary
    @includedlibrary
    Например, так:
    CC=gcc
    CFLAGS=-std=c11 -Wall -O3
    LDFLAGS=
    OBJ=$(patsubst %.c, %.o, $(wildcard *.c))
    TARGET=main
    .PHONY: all clean
    all: $(TARGET)
    $(TARGET): $(OBJ)
    	$(CC) $(LDFLAGS) $(OBJ) -o $(TARGET)
    %.o: %.c
    	$(CC) $(CFLAGS) -c $< -o $@
    clean:
    	rm -f $(OBJ) $(TARGET)
    Ответ написан
    Комментировать
  • Есть ли тайловый оконный менеджер, который работает с мышкой?

    includedlibrary
    @includedlibrary
    i3
    Ответ написан
    Комментировать
  • Возможно ли как-то использовать обычную функцию заместо макро-функции?

    includedlibrary
    @includedlibrary
    Да, возможно, но вы это делаете не правильно.
    #define PORTB 0x04
    #define PORTB0 0
    
    void bit_set(uint8_t port, uint8_t bit)
    {
        port |= (1 << bit);
    }
    
    int main(void)
    {
        bit_set(PORTB, PORTB0);
    }


    Здесь вообще ничего не делается, это же void функция. Если поменять её тип на uint8_t и добавить return, то компилятор всё равно оставит и функцию и её вызов, потому что она не объявлена статической, а значит может вызываться откуда-то ещё.
    #include <stdint.h>
    #include <stdio.h>
    
    #define PORTB 0x04
    #define PORTB0 0
    
    // вызов функции останется
    uint8_t bit_set(uint8_t port, uint8_t bit)
    {
        return port |= (1 << bit);
    }
    
    int main(void)
    {
        uint8_t res = bit_set(PORTB, PORTB0);
        printf("%hhd\n", res);
    }


    Если же сделать функцию статической, то её вызов будет заинлайнен, но лучше тогда сразу static inline использовать:
    #include <stdint.h>
    #include <stdio.h>
    
    #define PORTB 0x04
    #define PORTB0 0
    
    // А вот так функция будет заинлайнена
    static inline uint8_t bit_set(uint8_t port, uint8_t bit)
    {
        return port |= (1 << bit);
    }
    
    int main(void)
    {
        uint8_t res = bit_set(PORTB, PORTB0);
        printf("%hhd\n", res);
    }

    И да, чтобы переиспользовать static inline функции, их надо объявлять в заголовочных файлах, объявить прототип в заголовочном файле, а тело в .c файле не выйдет.
    Рекомендую проверить самостоятельно с помощью https://godbolt.org. Не забудьте, что без указания флагов оптимизации, ничего заинлайнено не будет, даже если объявить функцию, как static inline
    Ответ написан
  • Как исправить ошибку при выводе матрицы?

    includedlibrary
    @includedlibrary
    int input(int *n, int *m, int ***matrix, int *flag) {
        char ch;
        // Зачем считывать ch, я не понял. Также проверка у вас неправильная.
        // scanf возвращает число считанных элементов, вам надо сравнивать это
        // число с 2, так как вы считываете n и m.
        // if(scanf("%d%d", n,m) != 2 || *n <= 0 || *m <= 0)
        //     return 0;
        if (((scanf("%d%d%c", n,m, &ch)) || (ch != '\n')) && ((*n <= 0) || (*m <=0))){
            *flag =0;
            // Тут просто сделать return 0;
        } else{
            // Всё, что ниже, нужно вынести из else блока, а сам else блок убрать
            **matrix = (int *)malloc((*n) * sizeof(int*));
            for (int i; i < *n; i++ ){
            for (int j; j < *m; j++) {
                **matrix = (int *)malloc((*n * *m) * sizeof(int));
    
                // if(scanf("%d", &((*matrix)[i][j])) != 1)
                //     return 0;
                if (scanf("%d", matrix[i][j])) {
                    
                } else {
                   *flag =0;
                }
            }
        }
        } 
    // return 1;
    return *flag =1;
    }


    Тут вы используете неверный указатель:
    scanf("%d", matrix[i][j]) // так не надо
    scanf("%d", &((*matrix)[i][j])) // надо так
    scanf("%d", *(*matrix + i) + j) // или так


    Не понятно, зачем flag делать указателем, можно объявить его в input, присвоить 1 или 0 и вернуть. Кстати, у вас сравнение неверное, сейчас возвращается всегда 1:
    // очевидно, имелось в виду *flag == 1
    // Но вообще, можно просто вернуть *flag.
    // Или везде, заменить присваивание *flag = что_то на return что_то
    return *flag =1;


    Так же у вас абсолютно неверно выделяется память:
    // Тут каст неверный, должно быть (int**),
    // Но в си касты void* к другим типам указателей
    // можно опускать. Также нужна лишь одна операция разыменовывания для matrix
    **matrix = (int *)malloc((*n) * sizeof(int *));
    // Забыли присвоить 0 в i
    for (int i; i < *n; i++) {
      // А этот цикл надо сделать после выделения памяти для m столбцов
      // для ввода данных в выделенную память. Тут тоже забыли присвоить 0 в j.
      for (int j; j < *m; j++) {
        // Вот тут вы перезаписываете первую строку matrix,
        // хотя хотели выделить m столбцов для i строки.
        // До перазаписи дело, правда, не дойдёт, так как на предыдущем шаге
        // вы сделали два разыменовывания вместо одного и уже словили segfault
        **matrix = (int *)malloc((*n * *m) * sizeof(int));
        // ...
      }
    }


    Исправляется элементарно:
    *matrix = malloc(*n * sizeof(int*));
    for (int i = 0; i < *n; i++) {
        // *matrix - указатель на двумерный массив,
        // *matrix + i - указатель на строку (которая является указателем на одномерный массив),
        // *(matrix + i) = ... - присваивание указателю на строку адреса выделенной памяти
        *(*matrix + i) = malloc(*m * sizeof(int));
        for(int j = 0; j < *m; j++) {
            // Ввод данных
        }
    }


    Ну и совет на будущее - не используйте scanf, хотя проблема сейчас и не в ней. Желательно проверять результат malloc на NULL, чтобы корректно завершать программу в случае нехватки памяти, а не выводить segfault, или не завершать, а просто вызвращать ошибку и продолжать работу дальше. Также не используйте конструкции вида int ***matrix, лучше сделайте функцию, которая принимает n и m и возвращает указатель на матрицу, также сделайте отдельную функцию для ввода значений и вывода.

    int** create_matrix(int n, int m);
    bool read_matrix(int n, int m, int **matrix);
    void write_matrix(int n, int m, int **matrix);
    void free_matrix(int n, int m, int **matrix);


    Ну и 2 мерный массив можно сделать через одномерный, так будет меньше вызовов malloc, а значит потенциально меньше обращений к ядру. Также, если данные всего двумерного массива будут лежать последовательно, велика вероятность, что в циклах большая часть значений будет браться из кэша, а не из памяти, что даст выигрыш в скорости.
    int n = 10, int m = 5;
    int *matrix = malloc(sizeof(int) * n * m);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) {
            matrix[i * m + j] // обращение к элементу в i строке в j столбце
        }
    }


    Самое главное - пользуйтесь отладчиком, так вы всегда сможете понять, на какой строке у вас произошла ошибка.
    Ответ написан
    Комментировать
  • Не получается скомпилировать код?

    includedlibrary
    @includedlibrary
    Файл был пустой, поэтому clang не мог его скомпилировать. Либо вы компилировали другой файл, а не тот, что открыт в VScode, либо VScode не сохранял содержимое файла на диск.
    Ответ написан
    Комментировать
  • В чем ошибка кода?

    includedlibrary
    @includedlibrary
    int cubeI(int num) {
        if (num > 5) {
            cout << num << " ";
            return pow(num, 3);
        }
    }
    
    long cubeL(long num) {
        if (num > 5) {
            cout << num << " ";
            return pow(num, 3);
        }
    }

    Если элемент меньше или равен пяти, функции должны возвращать исходное значение. Нужно добавить return num после if, иначе будет возвращено то, что на момент выхода из функции было в регистре rax (если у вас amd64 архитектура).
    Ответ написан
    7 комментариев
  • На сколько безопасен sql запрос с подстановкой в него данных без обработки с клиента?

    includedlibrary
    @includedlibrary
    Можно прокинуть что угодно, следовательно так делать не безопасно. Чтобы избежать инъекций, используйте подготовленные выражения
    Ответ написан
    2 комментария
  • Как исправить ошибку Е0028 Выражение должно иметь константное значение на С?

    includedlibrary
    @includedlibrary
    Компилятор студии не поддерживает массивы переменной длины. Надо использовать malloс и free для выделения памяти. Но лучше не объявлять массивы переменной длины, так как это может вызвать переполнение стека при больших размерах.
    Ответ написан
    Комментировать
  • Верно ли я понял процесс преобразование целого типа данных в символьный на C?

    includedlibrary
    @includedlibrary
    В таблице ASCII все символы имеют 7 битный код, цифры расположены последовательно от 0 до 9, поэтому прибавление к значению от 0 до 9 кода сивола '0', вы получаете код символа, соответствующего данному значению. Но тип переменной не меняется, как был int, так им и остался.
    Ответ написан
    6 комментариев
  • Почему некорректно работает перегруженный оператор постинкремента?

    includedlibrary
    @includedlibrary
    На этой строке вы хотите скопировать вектор:
    Vector result = *this;

    Однако, у вас нигде нет конструктора на этот случай, поэтому у вас тупо копируется указатель, а не данные, которые по нему лежат. Надо добавить конструктор для этого:
    Vector(Vector &v) {
        this->dim = new double[v.dimCount];
        this->dimCount = v.dimCount;
        memcpy(this->dim, v.dim, this->dimCount * sizeof(double));
    }
    Ответ написан
  • На каком языке для каких целей писать проги под Symbian?

    includedlibrary
    @includedlibrary
    Симбиан мёртв, поэтому очевидно, что вы собираетесь писать для удовольствия. В таком случае берите тот язык, который больше нравится.
    Ответ написан
    Комментировать
  • Как записать текст из базы данных в txt файл делая отступы?

    includedlibrary
    @includedlibrary
    myfile = open('test.txt', 'w')
    Когда открываете файл в режиме 'w', вы открываете его на перезапись. Можно вместо 'w' передать 'a', тогда всё будет записываться в конец файла. Но, во-первых, в вашем коде один файл на всех пользователей (не знаю, была ли цель сделать именно так, поэтому пишу), во-вторых, могут быть дубликаты, т.е. желательно добавить проверку на уникальность. Можно взять СУБД (если нужно хранить всё в файле, то можно использовать sqlite), тогда и работать с несколькими пользователями будет проще и проверку на укникальность самому писать не придётся. Также использование СУБД позволит в будущем без проблем хранить какие-либо ещё данные, кроме URL прокси серверов
    Ответ написан
    Комментировать
  • Что за тип Unit в Haskel Rust Kotlin? Чем отличается от Void?

    includedlibrary
    @includedlibrary
    Тип Void в Haskell, в отличие от (), не имеет никаких значений. То есть вы не можете создать значение, имеющее данный тип. В свою очередь у () есть одно допустимое значение. Тип Void также встречается в системах проверки доказательств для обозначения ложности утверждения.
    Ответ написан
    Комментировать