Ответы пользователя по тегу C
  • Можно ли использовать в wasm загрузку dll библиотеки?

    Считайте что WebAssembly это отдельная платформа (не Windows, не Linux и не что-то еще), использовать Windows DLL в ней нельзя, если только вы не напишете / не портируете туда эмулятор Windows, использовать динамическую линковку можно, но между модулями написанными под wasm.
    Ответ написан
    1 комментарий
  • В какого типа переменных хранить адреса?

    В C используетсяvoid *, обратиться по нему без преобразования типа не получится
    Ответ написан
    Комментировать
  • Почему поведение fscanf ( stdin, "%c", &c ) различается при чтении EOF в msvc и gcc?

    ^Z / ^D не является "настоящим" концом файла, они не закрывают пайп, а заставляют терминал отправить пустой буффер ввода без установки кода ошибки, что в низкоуровневых функциях типа read() является признаком конца файла. Последующие вызовы read() могут продолжают возвращать данные, поэтому поведение зависит от того, как получение признака конца файла обрабатываются высокоуровневыми функциями типа scanf и реализации структуры FILE, а в случае Windows - еще и как в стандартной библиотеке реализованы файловые дискрипторы и низкоуровневые функции, т.к. в самой системе их нет - т.е. все зависит от реализации стандартной библиотеки С. Стандартом это поведение не регулируется. Кроме всего прочего, оно может отличаться для разных шелов и разных типов терминалов.
    Кроме того, как было замечено выше - нельзя использовать значения введенных scanf аргументов не проверив код возврата, если scanf вернул в вашем случае что-то отличное от 1 - они не определены.
    Ответ написан
  • Как скомпилировать C в FASM?

    Ассемблер это способ записи машинного кода, поэтому все, что можно скомпилировать / слинковать можно записать ассемблером. Но FASM - это не просто ассемблерная запись, фактически это язык программирования с высокоуровневыми конструкциями. Высокоуровневые конструкции нужны для читаемости кода человеком, а не машиной. Перевод кода из одного ЯП высокого уровня или машинного кода в другой язык программирования высокого уровня так, чтобы получился хороший читаемый код в общем случае задача практически нерешаемая и обычно ненужная, т.к. даже если возникает необходимость "скрещивать" языки программирования, то это делается на уровне статических или динамических библиотек. Даже если вы найдете что-то, что будет работать, оно будет работать не так, как вы ожидаете, сгенерированный код будет мало похож на код написанный человеком. Вы не описали задачу, которую хотите решить, но скорей всего вы пытаетесь ее решить способом, который для решения этой задачи не пригоден или по меньшей мере не оптимален.
    Ответ написан
    Комментировать
  • Как получить HMODULE импортированой dll без LoadLibraryA() или GetModuleHandleA()?

    Взять адрес ExitProcess и пройтись по страницам влево поискать в начале страниц PE-заголовок, по идее его адрес и должен быть HMODULE, но я не настоящий бинарщик.
    Ответ написан
    2 комментария
  • Как можно нарисовать пиксель на экране на ядре C?

    в C нет стандартных библиотек работы с графикой, поэтому варианты:
    1. Использовать системные функции (например Win32 API или X Window или более высокоуровневые типа KDE)
    2. Использовать универсальные интерфейсы, например OpenGL
    3. Использовать сторонние библиотеки для работы с графикой, например qt
    4. Напрямую работать с оборудованием (в случае если приложение запускается на голом железе, как драйвер ядра или в ОС которая позволяет напрямую адресовать видеопамять)
    Ответ написан
    Комментировать
  • Почему не правильно выводит значения d?

    %d это int, а передаете unsigned char.
    Ответ написан
    Комментировать
  • Как сделать ограничение на параллельное выполнение двух методов из разных процессов?

    Можно использовать:
    1. Именованные семафоры - "из коробки" предназначены для вашей задачи
    2. Неименованные семафоры + shared memory (на 1 и 2 есть примеры в https://stackoverflow.com/questions/8359322/how-to...)
    3. Атомарные переменные в shared memory (пример в https://stackoverflow.com/questions/48614784/alloc...) + футекс (футексы есть в линукс, но использовать их можно только через системный вызов, если что-то не поменялось) - наиболее эффективный способ, т.к. системный вызов дергается только если требуется блокировка процесса, но плохо документирован, если интересен поищите реализации критической секции через футекс, вам надо примерно то же самое
    4. мутексы в shared memory c PTHREAD_PROCESS_SHARED
    Ответ написан
    Комментировать
  • Как перехватить вывод в консоль из программы на С?

    Возможно несколько вариантов:
    1. Приложение пишет в stderr, тогда

    ./app 2>stderr.txt

    2. Приложение пишет в stdout но не считывает ничего с stdin

    по умолчанию вывод fprintf буферизован и буфер сбрасывается только при заполнении буфера, ожидании ввода или завершении программы. Можно либо отклюить буферизацию через
    setvbuf(stdout, NULL, _IONBF, 0);

    где-нибудь в начале программы, либо сбрасывать буффер принудительно через fflush(stdout); после каждого printf.
    Ответ написан
  • Почему не работает демон?

    1. В read наверняка надо передавать buf а не &buf (точно сказать нельзя т.к. описания нет)
    2. В зависимости от того, как вы запускаете процесс, дочерний процесс может получить SIGHUP при закрытии родительского процесса или SIGPIPE на printf, стоит добавить обработчики сигналов до fork().
    Ответ написан
    Комментировать
  • Какой компилятор для языка Си посоветуете?

    MSYS это набор POSIX-совместимых тулзов для Windows, он не имеет отношения к WSL2. MSYS2 вам не требуется, если вам не нужны тулзы, в качестве компилятора и библиотек он использует MinGW. MinGW тоже не имеет отношения к WSL. С помощью MinGW вы можете собирать родные Windows-приложения, собрать ими приложение под Linux не получится.

    Ответ в вашем случае - для изучения C по книжке скорей всего достаточно CodeBlocks+MinGW. WSL вам вообще не требуется. Он пригодится только если вы захотите разрабатывать приложения специфичные для POSIX или Linux.
    Ответ написан
    Комментировать
  • С помощью какой библиотеки парсить команды VT100 терминала?

    Не думаю, что требуется какая-либо специальная библиотека, возьми termcap-запись для VT100 (man termcap), она содержит набор всех управляющих последовательностей. Исключи эти последовательности из ввода (или добавь обработку, если требуется) - получишь только текстовые данные.
    Ответ написан
    Комментировать
  • Что не так в Eclipse IDE?

    Первый аргумент функции printf() char * а не char. Кроме того, первый аргумент это форматный спецификатор. Т.е. правильное использование printf("%c", x).
    Ответ написан
    1 комментарий
  • Char как UTF 16?

    Для Windows-платформ используется wchar_t (или WCHAR). Если код не специфичен для Windows, храните в 16-битных целых (uint16_t).
    Ответ написан
    Комментировать
  • Чем мой вариант хуже?

    Исходный код считывает строку (до \n) а ваш - просто читает данные в буффер пока другой конец не закроет сокет.

    Сравните все что есть в том коде и в вашем, что там есть и в вашем нет - того и не хватает. Например, возможны непрогнозируемые результаты (вероятней всего раскрытие содержимого памяти, т.к. остается неиницилизированный фрагмент с куском случайных данных из кучи в буфере) при наличии ASCII(0) в воде, не обрабатываются ошибки realloc() (что гарантировано приводит к повреждению памяти контролируемыми данными по частично контролируемому адресу, что с высокой вероятностью ведет к RCE, тем более что возможен heap spraying), код приводит к DoS-условиям с исчерпанием памяти, не терминируется текстовая строка и т.д. и т.п., т.е. только ошибок гарантированно влияющих на безопасность в вашем фрагменте не меньше 3х.

    P.S. справделивости ради, исходный код тоже не очень. Используется в 2 раза больше системных вызовов с копированием данных из ядра в память, чем фактически требуется, при этом размер буфера, в который производится чтение не соответствует размеру страницы, что дополнительно замедляет процесс. Чтобы этого избежать надо было добавлять буферизацию в юзерспейсе. Но в нем хотя бы явных проблем с безопасностью не видно.
    Ответ написан
  • Как ориентироваться в Gap buffer?

    Сделать с gap-буфером можно, информацию о позиции курсора храните отдельно при изменении позиции курсора меняете позицию gap, в общем-то оно на это и рассчитано.
    Я не знаю, как принято реализовывать в реальных текстовых редакторах, я бы сделал структуру похожую на btree без ключа
    https://ru.wikipedia.org/wiki/B-%D0%B4%D0%B5%D1%80...
    в каждом узле хранить либо указатель на фрагмент текста + его длину либо признак конца абзаца/спецсимвола либо ссылку на другой узел. Каждый фрагмент и строку хранить отдельным узлом.
    Фактически это возможность иметь неограниченное количество гапов в произвольных местах без необходимости их двигать. Как бонус, такая структура легко позволяет делать навигацию, undo/redo, т.к. каждая запись хранится отдельным узлом copy, paste и все остальное что обычно требуется. Поддержать форматированный текст так же очень легко, достаточно добавить признаки форматирования как еще один тип узла.
    Ответ написан
  • Как открыть новую консоль из программы?

    Не понятно где вы хотите новый терминал создать и что это за терминал. Если это xterm в X-сессии, например, то
    system("xterm -e ./newProg")
    если не xterm - то gnome-terminal, konsole или что-у-вас-там-стоит с нетелепатическим интерфейсом с соответствующей командной строкой.
    Ответ написан
    Комментировать
  • Как установить свой обработчик сигналов SIGUSR1 и SIGUSR2?

    man signal

    #include <signal.h>
    void sigprocess (int sign){
     /* process signal here */
    }
    
    ...
    int main(){
    ...
     signal (SIGUSR1, sigprocess);
    ...
    }


    P.S. если обработчик не нужен, можно
    signal(SIGUSR1, SIG_IGN);
    Ответ написан
    Комментировать
  • Почему send позволяет отправлять little-endian данные?

    Понятие big endian и little endian есть у многобайтных типов фиксированной длины (обычно целочисленных) в адресном пространстве. В сети нет адресации данных, поэтому нет понятия big endian и little endian, есть понятие прямого и обратного сетевого порядка байт.
    Функции send/recv оперируют не с многобайтными целыми числами, а с буфером памяти произвольной длины и ничего не знают о том, какие именно данные в этих буферах находятся и о представлении хранящихся в них целочисленных данных, если таковые там есть. Поэтому данные по сети будут отправлены в том порядке, в котором они находятся в адресном пространстве в отправляемом буфере.

    Однако, в привиденном вами фрагменте кода нет передачи челочисленных данных по сети, поэтому ваш вопрос в принципе не корректен. Ваши проблемы скорей всего в том, что вы отправляете лишние данные после текстовой строки, т.к. неправильно вычисляете количество символов в ней либо неправильно кладете в стек целочисленную переменную, без учета ее размера (например, там должно быть 64-битное число, а вы кладете только 32 бита).

    P.S. а вообще у вас там лишний бекслеш перед H в текстовой константе.
    Ответ написан
    Комментировать
  • Уязвимости типа переполнение буфера?

    Нет, вы поняли неправильно. Во-первых, эксплуатация переполнения буфера зависит от того, где расположен буфер. Скорей всего вы имеете ввиду переполнение стекового буфера aka stack overrun.
    При "классической" прямой эксплуатации переполнения буфера в стеке "по aleph1" в буфере размещается шел-код, затем сохраненный в стеке адрес возврата перезаписывается адресом, указывающим внутрь буфера (на шелкод), при возврате из функции выполняется шелкод.

    Однако, такие приемы работали до того, как появились технологии защиты стека, неисполняемой памяти и рандомизации размещения в адресном пространстве. Сейчас для эксплуатации переполнений стека на практике обычно требуются приемы ROP (return oriented programming), т.е. ваши знания очень сильно устарели.

    Написать программу и вставить ее код в чистом виде нереально даже в случае классической эксплуатации, т.к. шел-код должен быть привязан к определенному состоянию адресного пространства эксплуатируемого приложения, и попадает в адресное пространство минуя стандартные механизмы загрузки и динамической линковки. Обычно шел-код пишется на ассемблере, либо под определенные фиксированные адреса, либо так, чтобы не иметь привязки к адресному пространству или с учетом необходимых дополнительных операций (например получения адресов вызываемых функций) для привязки к адресному пространству.

    ROP представляет из себя в принципе иной подход к программированию, для разработки шел-кода предварительно необходимо собрать доступные фрагменты кода ("гаджеты"), возможность написания шел-кода зависит от собранных гаджетов и фактически требует трансляции кода в последовательность вызова гаджетов, обычные подходы к разработке кода здесь неприменимы (по крайней мере до того момента, как получен полный контроль над страницами памяти процесса).
    Ответ написан
    1 комментарий