Ответы пользователя по тегу C++
  • Почему ОС запускается на QEMU, а на Virtual Box нет?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему ОС не запускается на Virtual box, а на QEMU запускаеться?

    Потому что QEMU TCG не очень точно эмулирует x86. Если в командную строку qemu добавить -enable-kvm, то оно тоже не будет работать.

    А вот если добавить ret в реализацию GDT::load_gdt() и не вызывать load_tss() то оно начинает в qemu-kvm работать:
    diff --git a/src/GDT/GDT_impl.s b/src/GDT/GDT_impl.s
    index 4f69835abd9d..5476837f3d0a 100644
    --- a/src/GDT/GDT_impl.s
    +++ b/src/GDT/GDT_impl.s
    @@ -2,6 +2,7 @@
     .extern _ZN8SimpleOS3GDT7gdt_ptrE
     _ZN8SimpleOS3GDT8load_gdtEv:
            lgdt _ZN8SimpleOS3GDT7gdt_ptrE
    +       ret
     
     .global _ZN8SimpleOS3GDT8load_tssEv
     _ZN8SimpleOS3GDT8load_tssEv:

    Подозреваю, что и в virtual box оно заработает.
    Проблема в загрузке TSS, короче. Мне не знакомы дебри TSS, но для поверхностного взгляда кажется странным то, что все сегментные селекторы в твоём TSS имеют RPL=3, а селектор стека -- RPL=0.
    Если ты хочешь разбираться с тем, что происходит, то разумно было бы поменять порядок инициализации, сначала загрузить IDT, чтобы иметь возможность обрабатывать исключения, а потом загружать TSS и смотреть, что за исключение эта операция выкидывает.
    С другой стороны, непонятно зачем в текущей версии этой ОС нужен TSS. Подозреваю, что никакая функциональность не будет потеряна, если его не загружать.
    Ответ написан
    Комментировать
  • Расскажите пожалуйста как реализован sin в cmath?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    кода я не нашел, или плохо искал

    вот код из glibc.

    через ряд тейлора не вариант при больших значениях угла ряд медленно сходится

    В приведённой реализации сначала аргумент приводится к диапазону ±pi/2, потом берётся фиксированное число слагаемых ряда тейлора.
    Ответ написан
    1 комментарий
  • Как исправить ошибку в MakeFile?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    ругается на g++ -I $(INCL) $(SRCS) -o $(TARGET), как можно исправить?

    Заменить пробелы в начале строки одним табом. Команды в makefile начинаются с табов.
    Ответ написан
    Комментировать
  • Почему название файла в моей ОС изменяется само?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Проблема, как я вижу, зарыта в реализации метода map::copy, вот в этом месте. Нельзя копировать сложные объекты функцией memcpy(), потому что при удалении копии её деструктор освободит данные оригинала. Для такого копирования следует либо использовать placement new, либо копировать целиком объект Node, типа того. Для того чтобы это работало потребуется реализовать глобальный оператор new, типа того. С этими изменениями конкретно описанная в топике проблема решается, но я вижу, что и другие методы класса map реализованы с похожими ошибками, так что не расслабляйся и не думай, что это была единственная проблема в коде.

    Отдельный вопрос: зачем FileSystem::get_root() копирует всё дерево файловой системы, когда FileSystem::tree() явно не собирается его менять, можно было бы в этом случае обойтись константной ссылкой.
    Ответ написан
    1 комментарий
  • Не работает таблица прерываний(IDT). Что делать?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В чем может быть проблема?

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

    Вот эта структура:
    struct IDTPtr {
        uint16_t limit;
        uint32_t base;
    };

    должна быть определена с атрибутом packed, иначе компилятор вставляет паддинг для выравнивания поля base на границу uint32_t, из-за чего в IDT загружается неверный адрес.

    Ну и, вдобавок, нельзя делать iret из середины с++-функции, потому что компилятор организовал в ней кадр стека и вместо возврата iret снимает и интерпретирует мусор из этого кадра:
    001000e6 <SimpleOS::IDT::dividing_by_zero()>:
      1000e6:       55                      push   %ebp
      1000e7:       89 e5                   mov    %esp,%ebp
      1000e9:       53                      push   %ebx
      1000ea:       83 ec 04                sub    $0x4,%esp
      1000ed:       e8 15 01 00 00          call   100207 <__x86.get_pc_thunk.ax>
      1000f2:       05 06 11 00 00          add    $0x1106,%eax
      1000f7:       83 ec 0c                sub    $0xc,%esp
      1000fa:       8d 90 08 fe ff ff       lea    -0x1f8(%eax),%edx
      100100:       52                      push   %edx
      100101:       89 c3                   mov    %eax,%ebx
      100103:       e8 4c 00 00 00          call   100154 <SimpleOS::Terminal::print(char const*)>
      100108:       83 c4 10                add    $0x10,%esp
      10010b:       fa                      cli
      10010c:       cf                      iret
      10010d:       90                      nop
      10010e:       8b 5d fc                mov    -0x4(%ebp),%ebx
      100111:       c9                      leave
      100112:       c3                      ret
    Ответ написан
    9 комментариев
  • Error: no multiboot header found при загрузке своей ОС, как исправить?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Нужны подробности сборки. Согласно спецификации заголовок multiboot должен быть в пределах 8192 байт от начала, но если в сборку не подсовывать никаких дополнительных ключей и потом пытаться загружать elf-файл, то в нём multiboot header может оказаться дальше 8К от начала:

    $ gcc -m32 boot.s -nodefaultlibs -nostartfiles -Wl,-Tlinker.ld -no-pie -o boot.elf
    $ readelf -S boot.elf
    There are 8 section headers, starting at offset 0x3140:
    
    Section Headers:
      [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
      [ 0]                   NULL            00000000 000000 000000 00      0   0  0
      [ 1] .note.gnu.bu[...] NOTE            00100000 001000 000024 00   A  0   0  4
      [ 2] .multiboot        PROGBITS        00101000 003000 00000c 00      0   0 4096
      [ 3] .text             PROGBITS        00102000 002000 000009 00  AX  0   0 4096
      [ 4] .bss              NOBITS          00103000 003000 004000 00  WA  0   0 4096
      [ 5] .symtab           SYMTAB          00000000 00300c 0000a0 10      6   9  4
      [ 6] .strtab           STRTAB          00000000 0030ac 00004d 00      0   0  1
      [ 7] .shstrtab         STRTAB          00000000 0030f9 000044 00      0   0  1
    Key to Flags:
      W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
      L (link order), O (extra OS processing required), G (group), T (TLS),
      C (compressed), x (unknown), o (OS specific), E (exclude),
      D (mbind), p (processor specific)


    При такой сборке секция .multiboot оказалась по смещению 0x3000.
    Ответ написан
    Комментировать
  • Как ATmega88 подружить с кодом на С++?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Сигналы доходят до меги, но она не включает ни один из светиков.

    Я бы начал с отладки простым безусловным включением led на старте программы. Потому что 1К резистор последовательно со светодиодом с падением в 2В ограничивает ток 3ма, чего, скорее всего, недостаточно для заметного свечения.
    Ответ написан
    Комментировать
  • Try/catch и goto?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Для выхода из вложенных циклов при try/catch в случае исключения произойдёт свертка стека

    stack unwinding или развёртка стека происходит при выходе из одного или более вложенных вызовов, т.е. когда текущим должен стать более ранний кадр стека. При выходе из вложенных циклов в пределах одной функции кадр стека не меняется, но по правилам языка автоматические переменные из покинутых блоков должны быть уничтожены. Компилятор генерирует для этого код вызова деструкторов и вставляет его вызовы на пути выхода из блоков. В случае stack unwinding компилятор генерирует код вызова деструкторов, но вызов этого кода происходит более сложным путём. О том, как делается stack unwinding в gcc почитать можно здесь, о том как в этот процесс встраивается вызов деструкторов -- здесь.

    будет ли тоже самое для goto?

    То же самое будет и для goto.
    Ответ написан
    Комментировать
  • Почему время выполнения программы так сильно различается?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    … 75% cpu 2:23,52 total
    … 113% cpu 1:22,71 total
    … 73% cpu 2:20,75 total
    количество потоков в программе равно количеству потоков процессора (в моём случае - 8…

    Похоже, что твоя программа не справляется с загрузкой всех ядер, едва одно ядро она нагружает. Я бы смотрел в то как потоки взаимодействуют друг с другом и искал там явную или скрытую сериализацию.
    Ответ написан
    Комментировать
  • Как создать диалоговое окно без ресурсов?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как быть?

    CreateDialogIndirect принимает на вход в параметре lpTemplate указатель на структуру описывающую диалог.

    понял что проект VS обязательно должен быть оконным, в противном случае тупо не будет ресурсов

    вроде нет никаких ограничений по прикреплению ресурсов к консольным приложениям. Версия-то у них есть, а это же тоже ресурс.
    Ответ написан
    Комментировать
  • Почему теряется часть массива символов при его передаче по сокету?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    выяснил что проблема в sizeof(buf) который почему то равен 8 после передачи в функцию

    https://qna.habr.com/answer?answer_id=2411176#answ...
    Ответ написан
    Комментировать
  • Как можно разделить данный код (см. ниже) по header'ам и cpp'ам, учитывая зависимости в нём?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как я могу это сделать?

    Разносишь определения классов по файлам *.h. Разносишь определения методов классов по одноимённым файлам *.cc, инклудишь в них одноимённые *.h Потом смотришь на свою картинку. Стрелки наследования и агрегации добавляют include <файл в конце стрелки> в h файл в начале стрелки. Стрелки использования добавляют include <файл в конце стрелки> в cc файл в начале стрелки.
    Ответ написан
    1 комментарий
  • Как исправить ошибку буфера с UART?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    ONESTOPBIT ломало передачу блока

    Передачу откуда куда?

    DWORD ComIface::write(byte* data, int count)

    Что конкретно эта функция должна делать? Если это просто запись count байтов, то зачем так сложно?

    DWORD ComIface::read_block(byte* buffer, int size)

    Что конкретно эта функция должна делать?


    hpet rt;
        while (get_stats().cbInQue < size) {
            if (!SetCommMask(port_handle, EV_RXCHAR)) {
                printf("SetCommMask failed with error %d.\n", GetLastError());
                return NumberOfBytesRead;
            }
            WaitCommEvent(port_handle, &status, &overlap);
            WaitForSingleObject(overlap.hEvent, read_delay);
            if (rt.get_ms_dt_weak().count() > read_delay * size) {
                return NumberOfBytesRead;
            }
        }


    Что здесь происходит?

    Какие проблемы приводят к такому и как это чинить?

    Чтобы что-то чинить нужно это сначала понять.
    Ответ написан
  • Функция не работает, не понимаю почему, как можно исправить?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    что я сделал не так, подскажите пожалуйста
    if (b[i] >= x || b[i] <= y) {
      a[j] = b[i];
      j++;
    }
    ...
    if (b[i] < x || b[i] > y) {
      a[j] = b[i];
      j++;
    }

    Условия в операторах if не являются взаимоисключающими, а значит j может стать больше чем n и запись в a[j] вылезет за границу массива.
    Я не уверен в правильности первого условия, но особо не задумываясь можно второе условие переписать как прямое отрицание первого: if (!(b[i] >= x || b[i] <= y)) и это гарантирует, что индекс не выйдет за пределы массива, вне зависимости от правильности первого условия.
    Ответ написан
    Комментировать
  • Ошибка С2360, initialization of 'hInstanse' is skipped by 'case' label, почему?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    initialization of 'hInstanse' is skipped by 'case' label, почему?
    switch (uMsg)
    {
    ...
    case WM_CREATE:
    //получаем дескриптор приложения
    HINSTANCE hInstance = GetModuleHandle(0);
    ...
    break;
    
    case WM_MOUSEMOVE:
    //устанавливаем тот или иной курсор в зависимости от местонахождения мыши
    ...

    Потому что -- посмотри в этот код -- это фактически так: перейдя на метку WM_MOUSEMOVE код попадёт в область где hInstance определён, но минует его инициализацию. Компилятор туповат, чтобы понять, что hInstance дальше не используется. Простейший фикс -- обернуть код обработчиков в блоки:
    switch (uMsg)
    {
    ...
    case WM_CREATE:
    {
      //получаем дескриптор приложения
      HINSTANCE hInstance = GetModuleHandle(0);
      ...
    }
    break;
    
    case WM_MOUSEMOVE:
    {
      //устанавливаем тот или иной курсор в зависимости от местонахождения мыши
      ...
    }
    ...
    Ответ написан
    1 комментарий
  • Ошибка в подсчете символов, что делать?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    считать количество русских букв, однако он не правильно это делает, что не так?

    считать русские буквы сложно, твой код зависит от кодировки и в любой не-однобайтной кодировке этот код не будет работать правильно. Проще всего, мне кажется, выкинуть charVector и весь код связанный с ним, а оставшееся переписать следующим образом:
    setlocale(LC_ALL, "");
    
    const char *str = input.c_str();
    
    while (*str) {
        wchar_t c;
        int n = mbtowc(&c, str, MB_CUR_MAX);
    
        if (n < 0)
            break;
        if (wcschr(L"абвгд...юя", c))
            ++count;
        str += n;
    }
    Ответ написан
    1 комментарий
  • Как правильно вывести структуру из dll на c++ в Python?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Возврат структуры по значению при определённых условиях (связанных с размером и типами данных полей структуры) добавляет скрытый параметр (указатель на область памяти куда нужно вернуть результат), который функция будет ожидать. Это твой случай, и поэтому все остальные параметры съехали на один. Решение -- либо научить ctypes тому, что возвращается сложный тип и у функции может быть скрытый параметр (полагаю, что так: ctypes.restype(outdata), где outdata -- тип rez1, см), либо переделать функцию так, чтобы она не требовала скрытого параметра (например, добавив явный указатель на результат в список параметров, см).
    Ответ написан
    4 комментария
  • Compilation error: exit status 1?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    D:\ N E W\ 1637\ 1\Talking LED Alarm Clock Using TM1637 LED Module\Code/Code.ino:91: undefined reference to `sp3_THE'
    D:\ N E W\ 1637\ 1\Talking LED Alarm Clock Using TM1637 LED Module\Code/Code.ino:91: undefined reference to `sp3_THE'
    D:\ N E W\ 1637\ 1\Talking LED Alarm Clock Using TM1637 LED Module\Code/Code.ino:92: undefined reference to `sp3_TIME'

    В чему может быть проблема ?


    Так вот же написано: символы не определены. Поскольку компиляция прошла успешно, а проблема на этапе линковки, нужно добавить в линковку библиотеку в которой эти символы определены.
    Ответ написан
    Комментировать
  • Как можно улучшить код?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как можно улучшить код?

    - отформатировать по какому-нибудь стандарту, чтобы хотя бы строчки не гуляли влево-вправо.
    - пользоваться тернарным оператором вместо if когда это имеет смысл. На мой взгляд, d = n < 0 ? -n : n выглядит куда лучше семистрочного if/else.
    - не дублировать код когда этого легко избежать:
    if(n<0) {
        cout<<"-";
    }


    Ну и добавлю, что у этого кода есть проблема с обработкой входного значения -2147483648.
    Ответ написан
    Комментировать
  • Компиляция C++ кода на Ubuntu и Windows даёт мне разный результат, почему?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Уже не знаю что делать

    Не знаешь что делать -- включай санитайзеры:
    $ g++ -std=c++11 -g -fsanitize=undefined -fsanitize=address main.cc tools.cc -o test
    $ ./test
    ==3245365==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x606000000060 at pc 0x55b559719b47 bp 0x7ffcc39300a0 sp 0x7ffcc3930098
    READ of size 8 at 0x606000000060 thread T0
        #0 0x55b559719b46 in Processor::encode(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) toster/1320980/main.cc:41


    mainc.cc:41 это std::bitset<16> KR = K_array[i];, цикл по i идёт до 9, а в массиве K_array 8 элементов.
    Ответ написан