LINUX.ORG.RU

Cloudflare выпустила первый публичный релиз Pingora v0.1.0

 ,

Cloudflare выпустила первый публичный релиз Pingora v0.1.0

0

4

5 апреля 2024 года Cloudflare представила первый публичный релиз открытого проекта Pingora v0.1.0 (уже v0.1.1). Это асинхронный многопоточный фреймворк на Rust, который помогает создавать прокси-сервисы HTTP. Проект используется для создания сервисов, обеспечивающих значительную часть трафика в Cloudflare (вместо применения Nginx). Исходный код Pingora опубликован на GitHub под лицензией Apache 2.0.

Pingora предоставляет библиотеки и API для создания сервисов поверх HTTP/1 и HTTP/2, TLS или просто TCP/UDP. В качестве прокси-сервера он поддерживает сквозное проксирование HTTP/1 и HTTP/2, gRPC и WebSocket. Поддержка HTTP/3 — в планах. Pingora также включает в себя настраиваемые стратегии балансировки нагрузки и аварийного переключения. Чтобы соответствовать требованиям и безопасности, он поддерживает как широко используемые библиотеки OpenSSL, так и BoringSSL, которые соответствуют требованиям FIPS (федеральных стандартов обработки информации США) и пост-квантового шифрования.

Помимо этих функций, Pingora предоставляет фильтры и обратные вызовы, позволяющие пользователям полностью настраивать то, как сервис должен обрабатывать, преобразовывать и пересылать запросы.

В рабочем режиме Pingora обеспечивает плавный перезапуск без простоев для самостоятельного обновления, не теряя ни одного входящего запроса. Syslog, Prometheus, Sentry, OpenTelemetry и другие необходимые инструменты наблюдения легко интегрируются с Pingora.

Возможности Pingora: использование Async Rust, поддержка HTTP 1/2 end to end proxy, TLS over OpenSSL или BoringSSL, gRPC и проксирование веб-сокетов, Graceful reload, настраиваемые стратегии балансировки нагрузки и аварийного переключения, поддержка различных инструментов мониторинга.

В версии Pingora v0.1.1 исправлены ранее обнаруженные ошибки, улучшена производительность алгоритма pingora-ketama, добавлено больше бенчмарков TinyUFO и тестов для pingora-cache purge, ограничен размер буфера для журналов ошибок InvalidHTTPHeader, а также исправлены опечатки и внесены необходимые исправления в комментариях и документации проекта.

>>> Подробности

★★★

Проверено: hobbit ()
Последнее исправление: hobbit (всего исправлений: 1)

Ответ на: комментарий от vbr

Утверждение «практически весь код состоит из» довольно серьёзное. Если бы было написано «почти весь код в том одном файле, который я решил посмотреть», это было бы честней.

Я же написал, не было даже мыслей что из кучи файлов я попаду в тот самый где так много unsafe.

Что касается вашей речи про ssl я понял одно, не фига было вылазить с rust пока не сделали реализацию openssl на rust, по сути тут применение rust (его безопасность сведена к 0)

Кстати да, а что разве на rust еще не сделали реализации ssl ? Странно как то.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Кстати да, а что разве на rust еще не сделали реализации ssl ? Странно как то.

Давно сделали. Но криптография - штука такая, тут доверие особое нужно. К openssl доверие есть. К недавно появившейся библиотеке - нет. Когда речь идёт про криптографию, тут возможны многие классы ошибок, которые Rust не предотвращает автоматически: атаки по побочным каналам, логические баги. Полагаю, что по этим причинам многие предпочитают OpenSSL.

vbr ★★★
()
Ответ на: комментарий от vbr

К недавно появившейся библиотеке - нет.

Я думаю понимаете почему такое отношение к Rust в целом.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

не фига было вылазить с rust пока не сделали реализацию openssl на rust, по сути тут применение rust (его безопасность сведена к 0)

А теперь замените в предложении rust на, к примеру, java. Нелепо получается, не так ли?

unC0Rr ★★★★★
()
Ответ на: комментарий от unC0Rr

Вот к Java нет такого отношения. Нормальный синтаксис а самое главное ни кто никогда так не пихал rust во все щели, в ядро, переписыванием core-utils (да я понимаю это не крптография, тут дверия 0, можно и переписать на rust)

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Давай я объясню попроще.

Вот у тебя в коде есть говно. И в какой модули не ткнись - оно везде размазано тонким слоем, пованивает, привлекает мух и каждый раз, когда ты лезешь править этот файл, ты рискуешь вымазаться в нем и перемазать всё вокруг. Идея раста в том, чтобы собрать все это говно в одну кучу, накрыть колпаком с надписью unsafe, а остальные модули отмыть. Теперь все эти модули стали безопасными, и при работе с ними не получится испачкаться. А если надо покопаться в небезопасной куче - всегда есть химзащита.

liksys ★★★★
()
Ответ на: комментарий от liksys

Просто я UNIX да и Linux потом, всегда ассоциировал с си, в конце концов есть с++, стандарты и т.д. развивайте его в чем вопрос ?

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

Толи это такая непосильная задача написать сабж на си или ++, толи ума не хватает си осилить, не понятно.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Блин, я для кого метафору про говно сочинял?

В сях всё хорошо, но есть серьезная проблема: выход за границы массива, гуляние по невалидным указателям и прочие радости. Причем если ты посмотришь списки CVE, то большая часть уязвимостей будет вызвана именно ошибками при работе с памятью. И возникают они не потому что программисты тупые, а по невнимательности, это я тебе как активно пишущий на сях человек говорю.

Си сам по себе дубовый и простой, это буквально синтаксический сахар над ассемблером, и любые операции с более-менее сложными типами данных требуют пляски вокруг указателей и кастов через войд. Чего, на самом деле, для 99% задач в более высокоуровневых языках вообще не требуется. Поэтому придумали раст с ручным эффективным управлением памятью, но при этом обмазанный защитами. Unsafe, который смущает многих незнающих людей, нужен здесь затем, чтобы пристыковать небезопасный код на сях к безопасному на расте.

Еще раз: ты пишешь на расте оболочку для небезопасного кода. Оболочка маленькая, ее можно очень вдумчиво посмотреть и верифицировать. Когда ты, проанализировав ее, убеждаешься в безопасности, в дальнейшем ты можешь использовать ее в безопасном раст-коде, положившись на гарантии компилятора.

liksys ★★★★
()
Ответ на: комментарий от liksys

и любые операции с более-менее сложными типами данных требуют пляски вокруг указателей и кастов через войд

И самое главное - это не придурь отдельного программиста ради какого-то супер-экзотического случая, а вполне стандартная практика, и даже термин есть - type erasure. И эта практика зафиксирована в той же стандартной либе (см. функцию qsort).

seiken ★★★★★
()
Ответ на: комментарий от liksys

В сях всё хорошо, но есть серьезная проблема: выход за границы массива, гуляние по невалидным указателям и прочие радости.

Это видимо от того, что людям показывают как пользоваться «отладочной печатью» вместо отладчика, это от того, что не показывают как пользоваться линтером, санитайзерами и интерпретатором машинного кода.

Я не знаю что надо такого написать, чтобы это не заметил cppcheck, gcc -fsanitize=undefined,address и valgrind.

Только вот об ошибке мне инструменты скажут по существу. Все остальное время можно нормально писать код, а не заниматься тем, чтобы угодить компилятору.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

Я не знаю что надо такого написать, чтобы это не заметил cppcheck, gcc -fsanitize=undefined,address и valgrind.

void set5(char *s, char c)
{
   s[5] = c;
}

Кто-то из них ругнётся?

monk ★★★★★
()
Ответ на: комментарий от monk

А на что тут ругаться? Это корректный код.

А если ему будет передана строка менее, чем из 6 символов, то, да санитайзеры gcc и valgrind покажут ошибку и stack trace.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

А если ему будет передана строка менее, чем из 6 символов, то, да санитайзеры gcc и valgrind покажут ошибку и stack trace.

Да?

extern void f(char *s, char c);

void g()
{
   char s[3] = "ok";
   f(s, 5);
}

На этот код кто из них ругнётся? И на основании чего?

monk ★★★★★
()
Ответ на: комментарий от monk

Во-первых extern перед функцией ничего не значит. Он имеет смысл только перед глобальной переменной.

Во-вторых при сборке проекта с санитайзером в функцию f будет вставлена проверка выхода за границу.

zx_gamer ★★
()
Ответ на: комментарий от monk

На этот код кто из них ругнётся? И на основании чего?

На основании выхода за пределы массива, правда произойдет это только в runtime для твоего примера, но есть инструменты что бы такого не происходило:

void f(int n, char s[static n]);

int main() {
        char s[] = "ok";
        f(5, s);
}

main.c:5:9: warning: ‘f’ accessing 5 bytes in a region of size 3 [-Wstringop-overflow=]
    5 |         f(5, s);
      |         ^~~~~~~

MOPKOBKA ★★★★
()
Ответ на: комментарий от monk

Там и так есть extern, сработает где бы функция не находилась.

MOPKOBKA ★★★★
()
Ответ на: комментарий от zx_gamer

Я не знаю что надо такого написать, чтобы это не заметил cppcheck, gcc -fsanitize=undefined,address и valgrind.

$ cat test.cpp
#include <iostream>
using namespace std;

int table[4];
bool exists_in_table(int v)
{
    for (int i = 0; i <= 4; i++) {
        if (table[i] == v) return true;
    }
    return false;
}

int main()
{
    table[0] = 0;
    table[1] = 1;
    table[2] = 2;
    table[3] = 3;

    cout << "2 in table " << exists_in_table(2) << "\n";
}
$ g++ -fsanitize=undefined,address test.cpp
$ ./a.out
2 in table 1
$ g++ -O3 test.cpp
$ valgring ./a.out
==18435== Memcheck, a memory error detector
==18435== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==18435== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info
==18435== Command: ./a.out
==18435==
2 in table 1
==18435==
==18435== HEAP SUMMARY:
==18435==     in use at exit: 0 bytes in 0 blocks
==18435==   total heap usage: 2 allocs, 2 frees, 74,752 bytes allocated
==18435==
==18435== All heap blocks were freed -- no leaks are possible
==18435==
==18435== For lists of detected and suppressed errors, rerun with: -s
==18435== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

UB есть:

$ objdump -d ./a.out
...
00000000000011a0 <_Z15exists_in_tablei>:
    11a0:       b8 01 00 00 00          mov    $0x1,%eax
    11a5:       c3                      ret
...
monk ★★★★★
()
Ответ на: комментарий от monk

Если руки растут не из жёпы, то обычно все работает как надо))

test.cpp:8:20: runtime error: index 4 out of bounds for type 'int [4]'
test.cpp:8:20: runtime error: load of address 0x563232cd2ef0 with insufficient space for an object of type 'int'
0x563232cd2ef0: note: pointer points here
 03 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  00 00 00 00
              ^ 
=================================================================
==9971==ERROR: AddressSanitizer: global-buffer-overflow on address 0x563232cd2ef0 at pc 0x563232ccf323 bp 0x7fffe2e43150 sp 0x7fffe2e43148
READ of size 4 at 0x563232cd2ef0 thread T0
    #0 0x563232ccf322 in exists_in_table(int) /mnt/data/main/development/ansible/test.cpp:8
    #1 0x563232ccf4ef in main /mnt/data/main/development/ansible/test.cpp:20
    #2 0x7f79030456c9  (/lib/x86_64-linux-gnu/libc.so.6+0x276c9) (BuildId: 3b0430552f7704425a91887df0fcd734bf3c0f6f)
    #3 0x7f7903045784 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x27784) (BuildId: 3b0430552f7704425a91887df0fcd734bf3c0f6f)
    #4 0x563232ccf130 in _start (/mnt/data/main/development/ansible/a.out+0x2130) (BuildId: 30d7057078444035488f7ae70692393ed45cb847)

0x563232cd2ef0 is located 0 bytes after global variable 'table' defined in 'test.cpp:4:5' (0x563232cd2ee0) of size 16
SUMMARY: AddressSanitizer: global-buffer-overflow /mnt/data/main/development/ansible/test.cpp:8 in exists_in_table(int)
Shadow bytes around the buggy address:
  0x563232cd2c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x563232cd2c80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x563232cd2d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x563232cd2d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x563232cd2e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x563232cd2e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[f9]f9
  0x563232cd2f00: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
  0x563232cd2f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x563232cd3000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x563232cd3080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x563232cd3100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==9971==ABORTING
PRN
()
Ответ на: комментарий от PRN

Если руки растут не из жёпы, то обычно все работает как надо))

Покажи команду, которой проверял.

monk ★★★★★
()
Ответ на: комментарий от monk

Покажи команду, которой проверял.

У тебя код говно и ты это прекрасно знаешь. Ты бы еще бинарь не запускал, а потом включил дурачка и удивлялся: «А что оно не работает? А кто это сделал?» XD

PRN
()
Ответ на: комментарий от PRN

У тебя код говно и ты это прекрасно знаешь.

Так любой код с UB говно. zx_gamer заявлял, что инструменты в любом коде с UB, обнаружат его.

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

То есть ты модифицировал код, чтобы тестовый пример на неоптимизированном бинарнике попал на проверку.

Вот только это требует либо выдачи пользователю неоптимизированного бинарника с санитайзерами, теряя в скорости примерно в 4 раза, либо гарантировать, что при тестировании будут тесты на все случаи, где потенциально может быть UB (для сложной программы трудноосуществимо, иначе UB в том же gcc не попадалось бы).

monk ★★★★★
()
Ответ на: комментарий от monk

Так любой код с UB говно. zx_gamer заявлял, что инструменты в любом коде с UB, обнаружат его.

У тебя была сама проверка не корректна.

Вот только это требует либо выдачи пользователю неоптимизированного бинарника с санитайзерами

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

… для сложной программы трудноосуществимо, иначе UB в том же gcc не попадалось бы.

Осуществимо. Баги есть всегда не зависимо от их типа.

PRN
()
Ответ на: комментарий от PRN

Осуществимо. Баги есть всегда не зависимо от их типа.

Но когда это нормальный язык, пользователь предоставляет стек вызова, а в журнале есть контекст, в котором была ошибка. Когда же это Си++, то просто SegFault. Причём, как правило, не в тот момент, когда случилось UB, а чуть позже.

monk ★★★★★
()
Ответ на: комментарий от zx_gamer

Просто по умолчанию компилятор его не вшивает (нафиг он нужен в релизе?)

Чтобы не разбираться с ошибками пользователя «я что-то нажал и у меня Segmentation Fault», причём в коре видно, что у структуры объекта адрес испортился.

monk ★★★★★
()
Ответ на: комментарий от monk

Так в расте тоже разбираться надо

fn main() {
    let mut arr = [5; 1000000000000];
    arr[0] = 3;
    eprintln!("{:?}", &arr[0..1])
}

А про unsafe я вообще молчу. В C/C++ есть корки, по ним такие ошибки хорошо локализуются. Кстати в расте они есть?

PRN
()
Ответ на: комментарий от Silerus

Что такое корки?

https://wiki.archlinux.org/title/Core_dump

A core dump is a file containing a process’s address space (memory) when the process terminates unexpectedly. Core dumps may be produced on-demand (such as by a debugger), or automatically upon termination. Core dumps are triggered by the kernel in response to program crashes …

Берешь gdb и в путь)

tldr gdb
...
 - Debug with a core file:
   gdb -c core executable
...
PRN
()
Ответ на: комментарий от PRN

При панике разворачивается backtrace, как в питоне или лиспе, Надо чтоб была собрана дебаг версия и переменная RUST_BACKTRACE установлена в 1

Silerus ★★★★
()
Ответ на: комментарий от Silerus

Надо чтоб была собрана дебаг версия

Т.е. если к нам придут благодарные пользователе с релизной версией. Мы им ответим «спасибо» и пойдем балду пинать?)

PRN
()
Последнее исправление: PRN (всего исправлений: 1)
Ответ на: комментарий от PRN

Т.е паника может быть отключена в релиз версии настройками при сборки. Что бы не было «спасибо» и пошли балду пинать. Есть крейты log и log4rs (и другие аналоги). Где мы, как умные программисты, будем обрабатывать все Result и Option, а вместо a[9999999]=… использовать match a.get_mut(99999){ Some(…) =>{….},None=>{….}}

Silerus ★★★★
()
Ответ на: комментарий от Silerus

Есть крейты log

Вот только логи не сильно помогут в случае сегфолта, когда программа остановилась и буферы не скинуты. К тому же их еще надо расставить где надо.

мы, как умные программисты, будем обрабатывать

Что могу сказать) Если на Си писать правильно, то ошибок тоже нет))))

PRN
()
Ответ на: комментарий от PRN

Паника отключается в настройка - принудительно программистом. Если не отключить минимальный выхлоп мы получим. А кордамп операционка сама делает

Silerus ★★★★
()
Ответ на: комментарий от PRN

Так в расте тоже разбираться надо

Здесь хоть порчи памяти нет.

В C/C++ есть корки, по ним такие ошибки хорошо локализуются. Кстати в расте они есть?

Они в линуксе в любом бинарнике есть. Вот только когда у тебя в корке что-то вроде https://stackoverflow.com/questions/9809810/gdb-corrupted-stack-frame-how-to-debug , то как локализовывать будешь?

unsafe rust в этом смысле не лучше, но на нём можно писать маленькую, тщательно протестированную часть программы и не бояться, что добавка кода, украшающего кнопку, обвалит всю программу.

monk ★★★★★
()
Ответ на: комментарий от monk

Они в линуксе в любом бинарнике есть …

Есть то оно, конечно, есть. Но допустим в unsafe корнулось, что дальше? С сишными бинарями понятно: берешь gdb версию бинаря с дебажными символами и начинаешь дебажить. В расте только дебаг собирать?

PRN
()
Ответ на: комментарий от PRN

берешь gdb версию бинаря с дебажными символами и начинаешь дебажить.

В расте только дебаг собирать?

Так это одно и то же.

monk ★★★★★
()
Ответ на: комментарий от monk

Так это одно и то же.

Конечно же нет) Если надо корки мучить, то с сишке собирается релиз с дебажными символами (-O2 -g для примера), который бережно храниться. Стрипается, чтобы дебажных символов не было в релизе (man strip), и отправляется юзеру.

PRN
()
Последнее исправление: PRN (всего исправлений: 1)
Ответ на: комментарий от unC0Rr

О точно, с 1.57 появилось. Давно я ржавого не щупал) Так глядишь на нем скоро можно будет нормально кодить))

PRN
()
Ответ на: комментарий от unC0Rr

В смысле, в прод отправлять без проблем)

PRN
()
Ответ на: комментарий от PRN

Конечно же нет) Если надо корки мучить, то с сишке собирается релиз с дебажными символами

Теперь понял. Неоднозначность термина «дебаг».

Вот оптимизированный с дебажными символами в раст:

[profile.release-with-debug]
inherits = "release"
debug = true
monk ★★★★★
()
Ответ на: комментарий от PRN

Вот это вообще не отлавливается:

#include <iostream>
#include <string>

int main()
{
    std::string str = "hell";
    auto p1 = str.begin() + 5; // UB
    auto p2 = p1 - 3;
    str.erase(p2);
    std::cout << str;
}
monk ★★★★★
()
Ответ на: комментарий от mx__

Просто я UNIX да и Linux потом, всегда ассоциировал с си, в конце концов есть с++, стандарты и т.д. развивайте его в чем вопрос ?

У Си и Си++ есть возможность неопределённого поведения (UB), которое при наличии ломает всю программу.

У Rust есть подъязык без UB. И есть подъязык с UB, на котором можно писать программы, работающие не медленнее альтернативы на Си++. И эти два подъязыка прозрачно вызывают друг друга.

Если бы Java и С++ могли вызывать методы друг друга и имели совместимую систему типов, Rust был бы не нужен.

monk ★★★★★
()
Ответ на: комментарий от monk

Если бы Java и С++ могли вызывать методы друг друга и имели совместимую систему типов, Rust был бы не нужен.

Как говорил один мой неполиткорректный американский друг - if I was a nigger, my dick would be bigger. Видимо создать rust было проще чем преодолеть бюрократические и процедурные проблемы с совместимостью типов C++ и Java, что впрочем не удивительно.

Qui-Gon ★★★★★
()
Ответ на: комментарий от monk

У Си и Си++ есть возможность неопределённого поведения (UB), которое при наличии ломает всю программу.

А можно пример этого ? Или это про кодера по аналогии обезьяна с гранатой ? Ножом можно и огурец порезать а можно и зарезать.

P.S. Так и не увидел примеров прог на rust :(

mx__ ★★★★★
()
Последнее исправление: mx__ (всего исправлений: 1)
Ответ на: комментарий от mx__

Честно говоря не могу тут особо по деталям высказаться но общая суть претензий расто-хипстеров сводится к тому что на сишечке и плюсах можно сделать немного больше чем все. Так что компилятор тебе и слова не скажет. В этом сила - в этом и пролема. Опять же по аналогии. Автомобиль для езды - это некая комфортно мягкая штука с автоматикой племетикой шумоизоляцией минимумом приборов и а нынче еще и автопилотом. А автомобиль для ралли - это шумная телега где у тебя под оперативным контролем все - вместо привычного ABS там ручной ругулятор по перебросу тормозных усилий не по датчикам чтобы тормозить прямо - а как тебе надо. И шумки особой нет - пилоту надо слышать что там с движком происходит. И тд тп. И вот мы сажаем хороших раллийных пилотов в автоматику и в спортивный болид - спортивный просто порвет автомат как тузик. Сажаем чайника - ситуация до наоборот, чайник наверное с места то не тронется на спортивной машине. Но в абсолютном зачете спортивный пилот на спортивной машине будет недосягаем.

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

Собственно от этого и должен идти выбор языка. Какая задача проекта, кто и с какой квалификацией будет это писать, на какой железке это будет крутиться. Для пет-проекта у которого задача поучиться языку и себя показать - даже принцип «хочу раст потому что модно молодежно» - вполне уместен. Для продуктивного же обычно имеются архитекторы которые определяют стратегию развития.

Qui-Gon ★★★★★
()
Ответ на: комментарий от Qui-Gon

Да я все таки хочу услышать про реальные проги на rust :(

На всякий случай глянул inet, rust появился в 2006 году, а тот же go - 2009 …

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Я правильно понимаю, что критерий «реальной проги» не озвучивается намеренно, чтобы можно было отмахнуться от любого контрпримера словами вида «ну это не реальная прога»?

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от mx__

Firefox, Thunderbird - более чем реальные проги. Отличные. Лучший броузер и единественная альтернатива гугловской спайвари. Уже одних этих прог достаточно чтобы показать что будучи использован по назначению язык отличный.

Qui-Gon ★★★★★
()
Ответ на: комментарий от Qui-Gon

Человек выше привел проги и ок, поизучаю их. В своем время не понял как работает web framework на с++ и пришлось питон квырять :(

Что касается firefox и thunderbird то это вряд ли, у меня : firefox-115.9.1-1.el7.centos.x86_64 и в дистре нет rust, т.е. его бы не смогли в дистре собрать. Если будет не лень проверю зависимости сборки вряд ли там есть rust которого нет в дистре.

mx__ ★★★★★
()
Ответ на: комментарий от Qui-Gon

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

Можно поставить сверху общий блок unsafe и писать как на Си++.

monk ★★★★★
()
Ответ на: комментарий от monk

Можно поставить сверху общий блок unsafe и писать как на Си++.

А зачем? У каждого инструмента свое назначение. Но опять же повторюсь - для пет-проекта у корторого задача - показать потенциальному нанимателю вот как я могу - почему бы нет. Правда для тех нанимателей с которыми мне доводилось иметь дело проявление такой «крутости» это как правило минус а не плюс.

То есть пищущий такое на расте думает что он демонстрирует работодателю «вот как я виртуозно владею инструментом». А работтодатель видит другой посыл - «кандидат не умеет правильно выбирать инструмент под задачу».

Qui-Gon ★★★★★
()
Последнее исправление: Qui-Gon (всего исправлений: 1)
Ответ на: комментарий от Qui-Gon

А зачем? У каждого инструмента свое назначение.

Затем, что если поверх C++ надо прикрутить безопасные компоненты, то надо долбаться с FFI и extern C. А если к Rust, то просто слинковать модуль без unsafe.

monk ★★★★★
()
Ответ на: комментарий от Qui-Gon

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

Ты под чем-то, скажи честно? Долбите на пару с @mx__? Вам сколько раз уже объяснили, что программистские проблемы не в языке, а в алгоритмической сложности, и области знаний? Что CVE возникают не на пустом месте?

Как об стенку горохом - продолжаете нести свой бред про неумелые руки и заговоры для замены всех индусами.

liksys ★★★★
()
Последнее исправление: liksys (всего исправлений: 1)
Ответ на: комментарий от liksys

Вам сколько раз уже объяснили, что программистские проблемы не в языке, а в алгоритмической сложности, и области знаний

Вот мне почему то кажется что это вам ровно это объясняли. Но вы все пищите раст решает все проблемы в дидовской сишке.

заговоры для замены всех индусами

это не заговоры а мировая практика. Причем не индусами - а дешовыми индусами(цыганами пакистанцами хуситами покорителями верхнего ларса - национальность не важна, важна готовность кодить за еду). Так роботает индустрия. Дешовый индус набравшись опыта и знаний отказывается кодить за миску риса, переезжает жить в Лондон (или Купертино или еще куда). Капиталиста волнует только прибыль - а прибыль это доходы минус расходы. Когда ChatGPT*(без понятия как этот скайнет будет называться) научится кодить - все вы ( и мы тоже - что уж тут ) окажемся в очереди у бака с пищевыми отходами как в 30-е годы прошлого века. Но это немного другое. Вам милостивый государь не понять скорее всего - и это ваше счастье. Многие знания умножают скорбь, так что наслаждайтесь юношеским максимализмом пока можете.

Qui-Gon ★★★★★
()
Ответ на: комментарий от Qui-Gon

Когда ChatGPT*…научится кодить

Тогда появиться еще 344 новых профессии, как в случе появления Excel. Который забрал работу у счетоводов которые как раз вручную и занимались переписыванием цифорок в клеточках.

UPD:

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

lbvf50txt
()
Последнее исправление: lbvf50txt (всего исправлений: 3)
Ответ на: комментарий от lbvf50txt

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

Но это по большей части были уже другие люди. Вам же похрен - вы цари, всегда будете при бабле на мерседесе и руководящей должности. А за едой в благотворительной столовой будет стоять кто-то другой. Но на практике так не бывает. Вылетевший на улицу счетовод может попробовать пойти в админы или программисты - но тут вопрос 0 есть джун 40 лет который откончил курсы админов и джун 18 лет. Кто получит работу догадываетесь? Такие технические переломы индустрии всегда вытекают в социальное напряжение.

Загуглите фотографии хуситов в шлепанцах с автоматами, кинжалами за традиционным поясом, шеками раздутыми от листьев ката и представте что они комитят в GitHub в проекты на Rust.

Хуситы в шлепанцах хоть и не без помощи тайных друзей отлично бомбят дронами корабли высокоразвитой технологической цивилизации, а еще недавно гиперзвук испытали. Так что внешность весьма обманчива. Ради интереса погуглите как в ковид индусы в шлепанцах где-то в трущобах запускали жидкостную ракету. Сварили их труб говна и палок, выморозили из атмосферы кислород. Понятно что это был не космос но имея в руках только газосварочный аппарат и кучу мусора они это сделали.

Знания доступны - по сути дела все упирается в способность индивидуума их впитать. Посмотрите репортажи из трущоб - там даже у детей телефоны с интернетом.

А шлепанцы - ну там тепло, шуба не нужна с валенками. А листья ката - не знаю сильно ли они лучше аддерала на котором сидит львиная доля элитных прогеров долины, или травки с пивком и абсентиком которые не чужды нащим относительно законопослушным дарованиям.

Так что рекомендую вам затолкать свое чувство сытого превосходтсва над «жалкими» хуситами поглубже и посмотреть что происходит в мире.

Qui-Gon ★★★★★
()
Ответ на: комментарий от Qui-Gon

Вылетевший на улицу счетовод может попробовать пойти в админы но тут вопрос 0 есть джун 40 лет который откончил курсы админов и джун 18 лет.

Вот тут логическая ошибка. Счетовод из 80ых ставится в современные условия. В момент распространения Excel-подобных программ, требования к «компьютерщикам» были другие. Буквально человек который способен набрать текст в редакторе уже обладал профессией.

Вам же похрен

Нам не похрен. Для того чтоб оставаться на плаву надо постоянно учиться. Изучать Rust, systemd и прочие обхаиваемые нововедения, дабы не окзаться «счетоводом».

«жалкими» хуситами поглубже

Хуситы не жалкие. Это люди из формации родоплеменного строя: где учатся обращаться с оружием, а не программировать.

lbvf50txt
()
Последнее исправление: lbvf50txt (всего исправлений: 3)
Ответ на: комментарий от lbvf50txt

Нам не похрен. Для того чтоб оставаться на плаву надо постоянно учиться. Изучать Rust, systemd и прочие обхаиваемые нововедения, дабы не окзаться «счетоводом».

Там одних только js целая куча (react,vue…), плюс всякие go, vala и т.д., у одного только прометея свой язык запросов к БД…

Как говорил ШерлокХ, мозг чердак и не нужно тащить туда всякий хлам. Вот и думаешь что надолго а про что через 5-10 лет забудут.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Как говорил ШерлокХ

Прежде всего Шерлок Холмс это вымышленый герой подростковой экшн книги.

В том же эпизоде Шерлок Холмс отличал улицы Лондона по грязи на подошве и тип сигары по пеплу.

Там одних только js целая куча (react,vue…),

Сейчас FrontEnd превратился в отдельную профессию, и если кто-то решил стать профессиональным фронтендером то ему надо знать и react и vue. Профессия востребованая, хорошо оплачиваемая, но сложная: надо отслеживать множество изменений в инструментах.

плюс всякие go

Вот вы смешиваете разные уровни: фреймворки и языки программирования. Чем больше программист знает языков, тем лучше он понимает как использовать базовые составляющие: объекты, массивы, исключения, замыкания, наследования, композиции, функции первого порядка. В каждом языке какая-то идея доведена до совершенства, и поняв ее в побочном для себя языке пишешь код лучше на основном.

lbvf50txt
()
Последнее исправление: lbvf50txt (всего исправлений: 1)
Ответ на: комментарий от lbvf50txt

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

Да. Поэтому я считаю, что знать надо, как минимум, схему, форт, хаскель и с++. Вне зависимости от того, на чём потом писать будешь.

monk ★★★★★
()
Ответ на: комментарий от monk

вот честно говоря зачем хаскель - не знаю. тут как раз буду за раст - его хоть где-то применить можно, а хаскель это сектантство какоето. И питон в студию - по крайней мере для линуксоидов. На нем столько всего понаписано что даже если самому на нем что-то писать религия не позволяет - то хоть разбираться в том что понаписано и работает на твоем компе желательно уметь.

Qui-Gon ★★★★★
()
Ответ на: комментарий от Qui-Gon

вот честно говоря зачем хаскель - не знаю.

Потом на других языках интуитивно раскидываешь задачу на функции, которые идеально сочетаются с модульными тестами.

И идея класса типов хороша для проектирования даже на питоне.

monk ★★★★★
()
Ответ на: комментарий от Qui-Gon

И питон в студию - по крайней мере для линуксоидов.

Питон, перл, баш, … — это всё надо, но от них польза в других языках минимальна.

monk ★★★★★
()
Ответ на: комментарий от monk

Да. Поэтому я считаю, что знать надо, как минимум, схему, форт, хаскель и с++.

Согласен. Звучит роскошно, но требует дисциплины, Хаскель и Lisp это уж очень теоретические языки.

Даже более прикладные языки и хорошие спикеры дают кругозор.

К слову Спикеры - не нравится мне этот термин. Как этих людей по русски назвать: учителя, мастера, докладчики, авторы? Авторы.

lbvf50txt
()
Последнее исправление: lbvf50txt (всего исправлений: 2)
Ответ на: комментарий от lbvf50txt

Согласен. Звучит роскошно, но требует дисциплины, Хаскель и Lisp это уж очень теоретические языки.

Для меня скорее форт оказался теоретическим языком: я на нём решал только учебные задачи. На хаскеле удобно писать обработку текста, на схеме у меня почти все локальные программы от сайта до обмена сообщениями.

monk ★★★★★
()
Ответ на: комментарий от monk

На хаскеле удобно писать обработку текста

Хаскель настойчиво рекомендуют выучить, даже в роликах посвященных Rust.

lbvf50txt
()
Ответ на: комментарий от mx__

Приятно обсудить 2*2=4 за чашечкой кофе в форуме. Как говориться обсуждать Perl не мешки ворочать. Изучать же новые концепции сожно, муторно и скучно, в час по чайной ложке и тянет на LOR.

lbvf50txt
()
Ответ на: комментарий от lbvf50txt

Хуситы не жалкие. Это люди из формации родоплеменного строя: где учатся обращаться с оружием, а не программировать.

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

Буквально человек который способен набрать текст в редакторе уже обладал профессией.

Это у вас ошибка - вы смотрите с современных условий и вам кажется что уж что то а набирать текст в редакторе может даже идиот из школы для умственно отсталых. А уж человек с вышим образованием даже не айтишным - и подавно. Но тогда умение на машинке печатать было профессией которой владели немногие. И почтенный счетовод который 30 лет туда-сюда гонял костяшки на счетах и обладал каллиграфическим почерком вдруг оказывался со своими уже закостеневшими навыками и медленно перестраивающимися нейронными связями за бортом с необходимостью начинать игру сначала. И все что он умел и делал 30 лет до этого ему увы никак не помогало, эти навыки более того были лишними. Особенно на фоне вчерашнего школьника с гораздо более гибкой нервной системой и уже базовыми навыками. Да и первые эти системы были не настолько user-friendly как нынешние - в тех первых досовских еще и win 3 редакторах и таблицах надо было разбираться.

Изучать Rust, systemd и прочие обхаиваемые нововедения, дабы не окзаться «счетоводом».

Ну тут не поспоришь - дедушка Ленин еще в прошлом веке на чердак - и учиться учиться учиться. Но вот насчет нововведений - не уверен. Но новое и модное кидается молодежь - помните как в «аватаре» - моя чаша пуста, все вольется. И конкурировать с хипстерами на их поле для «счетоводов» проигрышная стратегия. Но просто на попе ровно не усидишь, и тут в какой-то мере лотерея. Скажем кобол вроде как мертвый язык - почти латынь. Но до сих пор дохрена систем на коболе менять которые - долго, дорого и небезопасно. Поэтому оставшиеся в живых носители кобола очень даже в цене. Это какбы частные пример - тут цена выросла не из-за огромного спроса а скорее из-за сильно упавшего предложения. То есть общего решения для счетовода нет, но наверное две стратегические рекомендации - учиться (сидеть на попе ровно не прокатит) и при этом избегать самых модных популярных направлений ( в него побегут только лишь все )

Qui-Gon ★★★★★
()
Ответ на: комментарий от Qui-Gon

Вам тоже кофий. Забористо пишете, агрессивно чуть чуть. Но за то со вкусом, ярко.

lbvf50txt
()
Ответ на: комментарий от Qui-Gon

Вот мне почему то кажется что это вам ровно это объясняли.

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

Но вы все пищите раст решает все проблемы в дидовской сишке.

До вас, клоунов, никак не доходит, что раст решает не все, а одну вполне конкретную проблему обращения к памяти. Но вы втемяшили себе какую-то чушь о якобы золотопульном расте, и теперь хоть кол на голове чеши - вообще не слышите, что вам говорят.

Так роботает индустрия.

Об индустрии рассуждает кекс, который даже на своем языке не в состоянии изъясняться без явных орфографических ошибок.

liksys ★★★★
()
Ответ на: комментарий от liksys

До вас, клоунов, никак не доходит,

Зря вы так. Это клондайк!

Загуглите фотографии хуситов в шлепанцах с автоматами, кинжалами за традиционным поясом, шеками раздутыми от листьев ката и представте что они комитят в GitHub в проекты на Rust.

Ну где вы еще такое найдете?

lbvf50txt
()
Ответ на: комментарий от lbvf50txt

Ага, орут и тычат в расктрытый K&R пальцами.

liksys ★★★★
()
Ответ на: комментарий от liksys

До вас, клоунов, никак не доходит, что раст решает не все, а одну вполне конкретную проблему обращения к памяти.

Не одну, а все, которые в сишке приводят к неопределённому поведению. Их много: https://github.com/Nekrolm/ubbook

monk ★★★★★
()
Ответ на: комментарий от liksys

Остальные проблемы сишки успешно решает Си++.

А этот набор проблем раньше решали языки со сборщиком мусора (лисп, джава, сишарп, питон, …). Но они медленные и взаимодействие с Си++ не особо простое.

Раст в безопасном варианте работает в среднем быстрее и взаимодействие с небезопасным растом полностью прозрачное. Цена: ограничения на разнообразие алгоритмов в безопасном варианте и борьба с компилятором.

monk ★★★★★
()
Ответ на: комментарий от monk

Остальные проблемы сишки успешно решает Си++.

Плюсы это страх и ужас, и они создают проблем больше, чем решают, главным образом с сопровождением. Я знаю, что на нем можно писать нормально, но это настолько редко встречается, что скорее нет.

liksys ★★★★
()
Ответ на: комментарий от liksys

И чем, по-твоему, заменить плюсы?

Решаемые проблемы объективны: использование шаблонов вместо макросов, RAII, параметризованные типы и автовывод типов, функторы, …

monk ★★★★★
()
Ответ на: комментарий от liksys

То есть в своей нише (нужна максимально быстрая программа) плюсы являются наилучшим языком из существующих?

monk ★★★★★
()
Ответ на: комментарий от monk

Если утрировать и не делать деления на cpu/io-bound, то в принципе да. С другой стороны, всегда можно разные части системы писать на разных языках. Редко где нужна производительность программы целиком, достаточно писать особо критичные куски на сях или плюсах.

liksys ★★★★
()
Ответ на: комментарий от liksys

С другой стороны, всегда можно разные части системы писать на разных языках.

Вот для этой ситуации и придумали Раст. Программный интерфейс Си++ практически невозможно дёргать напрямую ни из одного безопасного языка. И накладные расходы на межъязыковое взаимодействие с Си++ такие, что нельзя сделать на Си++, например, только внутренности какого-нибудь горячего цикла. Надо весь цикл переписывать. И всё, что в процессе из него вызывается.

А в Раст внутренности цикла на unsafe rust, всё остальное на safe, потери на взаимодействие частей нулевые.

monk ★★★★★
()
Ответ на: комментарий от monk
Ответ на: комментарий от mx__

https://ru.stackoverflow.com/questions/548017/%D0%9A%D0%B0%D0%BA-%D0%B2-golang-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-c-%D0%B8%D0%BB%D0%B8-c-%D0%BA%D0%BE%D0%B4

Вот это я и имел в виду. На 7 строчек интерфейса Си++ надо 30 строк обвязки в Си++ и 20 в Go. Плюс, если функция Си++ возвращает не число, а что-то полезное (например, std::map<std::string, int> хотя бы), то развлечения ещё на порядок больше.

monk ★★★★★
()
Ответ на: комментарий от monk

Мне объяснять не надо, я-то всё прекрасно понимаю :)

Вот где плюсы действительно почти безальтернативны - гуевый кроссплатформенный софт. Мне в прошлом году понадобилось софтину одну написать, и пришлось лабать на плюсах с Qt.

PS: Электрон не предлагать.

liksys ★★★★
()
Последнее исправление: liksys (всего исправлений: 1)
Ответ на: комментарий от unC0Rr

Можно. Я люблю питон, но учитывая, что там уже были кусочки, критичные к производительности, а сама софтина была не сильно большая, плюсы были проще. И потом, я и так намучился с упаковкой его в setup.exe и dmg, а тут питон еще.

liksys ★★★★
()
Ответ на: комментарий от liksys

PS: Электрон не предлагать.

Ещё Gtk есть, к которому интерфейс с любого языка. И Avalonia. И Java. Это всё лучше, чем отлаживать неожиданное UB.

monk ★★★★★
()
Ответ на: комментарий от monk

Ещё Gtk есть, к которому интерфейс с любого языка.

Хуже придумать сложно.

И Java

Вышел Intel Core i48. Наконец-то достойный соперник Java.

Это всё лучше, чем отлаживать неожиданное UB.

UB неожиданно для тех, кто на языке писать не умеет.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

UB неожиданно для тех, кто на языке писать не умеет.

UB может быть просто от опечатки. И я уже приводил пример UB даже в коде сишного компилятора.

monk ★★★★★
()
Ответ на: комментарий от zx_gamer

Не везде можно обратиться по указателю на уже освобождённую память. Не везде INT_MAX + 1 это UB. Да в этом Си даже написать цикл от a до b включительно не каждый осилит написать.

unC0Rr ★★★★★
()
Ответ на: комментарий от zx_gamer

Так везде. Везде можно перепутать + 0 и / 0.

Да. Но если у тебя нормальный язык, то именно в этой точке будет ошибка с нормальной трассой стека. А если UB, то эта точка может просто вообще пропасть из программы вместе со всеми командами до и после ошибки.

monk ★★★★★
()
Ответ на: комментарий от liksys

Так надо и писать, что «плюсы действительно почти безальтернативны среди тех языков, на которых я пишу, и тех графических библиотек, что мне нравятся».

Даже на схеме есть racket/gui, который переносим не хуже Qt.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

среди тех языков, на которых я пишу, и тех графических библиотек, что мне нравятся

Давай только не путать Qt-фреймворк с графичиескими библиотеками. Берешь Qt - и у тебя есть сеть, ком-порты и почти всё, что может понадобиться среднему десктопному софту. Для остального придется городить идеоматический огород.

liksys ★★★★
()
Ответ на: комментарий от liksys

Ты писал «гуевый кроссплатформенный софт». Сеть и ком-порты к гуёвому софту перпендикулярны.

Вообще в любом кроссплатформенном языке, от лиспа до питона, практически все библиотеки кроссплатформенны.

Си++ нужен только когда тебе нужна не просто сеть, а сеть с максимально быстрой обработкой данных. И ты согласен за это рисковать лишним временем отладки и возможным наличием загадочных ошибок при работе.

monk ★★★★★
()
Ответ на: комментарий от monk

Ты писал «гуевый кроссплатформенный софт». Сеть и ком-порты к гуёвому софту перпендикулярны.

Писал, уточняю.

Вообще в любом кроссплатформенном языке, от лиспа до питона, практически все библиотеки кроссплатформенны.

Я там выше еще писал про идеоматичность.

liksys ★★★★
()
Ответ на: комментарий от liksys

Qt относительно Си++ очень плохо идеоматичен. Постоянные преобразования между QString и std::string. Его даже обычным компилятором Си++ не скомпилировать.

monk ★★★★★
()
Ответ на: комментарий от zx_gamer

А разве для Qt уже не требуется компиляция через moc?

monk ★★★★★
()
Ответ на: комментарий от monk

Постоянные преобразования между QString и std::string

Зачем? Впрочем, многие библиотеки заставляют перегонять из своих контейнеров в стандартные или чужие. Пишу на работе приложение в связке из Qt и osgEarth, в osgEarth свой ref_ptr, свой optional, свои векторы и матрицы, свой тип для геокоординат, вот и приходится обмазывать всё клеем, гоняя данные между разными библиотеками.

unC0Rr ★★★★★
()
Ответ на: комментарий от monk

Это как раз не сильно большая проблема. Я про то, что для стыковки обычных библиотек с гуем надо потратить немножко сил, в то время как кутешные либы с кутешным же гуем стыкуются без всяких проблем (было бы странно, если нет).

liksys ★★★★
()
Ответ на: комментарий от liksys

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

Питоновские обычные библиотеки даже с гуем на Qt легче стыкуются, чем обычные C++.

Если брать стыковку библиотек Racket с racket/gui, то там всё вообще идеально.

monk ★★★★★
()
Ответ на: комментарий от liksys

Нет, это зависит от библиотеки.

Преобразований между std::string и QString и std::list и QStringList не избежать.

То есть, там, где в питоне я просто пишу:

widget.addItems(lib.data())

в С++ приходится писать что-то вроде

widget.addItems(toQStringList(lib.data()))

и так на всех стыках между моделью и отображением.

monk ★★★★★
()
Ответ на: комментарий от monk

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

liksys ★★★★
()
Ответ на: комментарий от liksys

Поэтому в том месте, где Qt ты с большой вероятностью сможешь построить приложение только из самого Qt

Вот поэтому я и считаю Qt де-факто отдельным языком.

monk ★★★★★
()
Ответ на: комментарий от liksys

Фреймворки бывают идиоматическими (которые можно использовать совместно с базовой библиотекой и друг с другом) и неидиоматическими (как Qt в C++).

К слову, в Python основанный на Qt PySide является идиоматическим: в нём нет своих версий строки и коллекций, которые уже есть в базовом языке. И не требуется отдельного синтаксиса для сигналов и слотов (для слота есть декоратор).

monk ★★★★★
()
Ответ на: комментарий от monk

Фреймворки бывают идиоматическими (которые можно использовать совместно с базовой библиотекой и друг с другом) и неидиоматическими (как Qt в C++).

Ты это деление сам только что придумал?

  • Qt использует свой препроцессор, но все еще преобразуется в обычный плюсовый код.
  • Посмотри на прототипы в Qt - увидишь кучу стыкующихся функций с обычными плюсовыми типами.
liksys ★★★★
()
Ответ на: комментарий от liksys

Qt использует свой препроцессор, но все еще преобразуется в обычный плюсовый код.

Я больше про NIH-синдром на все базовые типы.

Когда в питоне можно писать

table.setHorizontalHeaderLabels(["Name", "Hex Code", "Color"])

а в C++ надо собирать через

QStringList horzHeaders;
horzHeaders << "test1" << "test2" << "test3";
table.setHorizontalHeaderLabels(horzHeaders);

В Common Lisp такой же hu.dwim есть. Вроде библиотека, но при использовании любого кусочка надо тащить почти весь фреймворк и при использовании свои описания пакетов и классов.

monk ★★★★★
()
Ответ на: комментарий от monk

NIH-синдром на все базовые типы

Это не NIH, а вполне оправданная унификация компонентов, чтобы не использовать тысячу и один каст. 99% всех кейсов при работе со строками и списками отлично покрываются Qt. Плюс строки в кишках используют неявное кеширование, чтобы экономить память.

а в C++ надо собирать через

table.setHorizontalHeaderLabels(QStringList() << "test1" << "test2" << "test3");

Слава богу, Qt делали умные люди.

liksys ★★★★
()
Ответ на: комментарий от liksys

Это не NIH, а вполне оправданная унификация компонентов, чтобы не использовать тысячу и один каст.

Вот есть libyue. Идиоматичная библиотека графического интерфейса. Где строки — это std::string, строки таблицы выбираются через std::set, а не QTableWidgetSelectionRange, пометка текста делается двумя числами, а не через QTextCursor.

monk ★★★★★
()
Ответ на: комментарий от monk

Потому что это библиотека гуев, а не фреймворк.

liksys ★★★★
()
Ответ на: комментарий от liksys
table.setHorizontalHeaderLabels({"test1", "test2", "test3"});

upd а выше монку ответили такое же (:

arcanis ★★★★
()
Последнее исправление: arcanis (всего исправлений: 1)
Ответ на: комментарий от liksys

Посмотри на прототипы в Qt - увидишь кучу стыкующихся функций с обычными плюсовыми типами.

Ага. Эдакий FFI к остальному Си++.

monk ★★★★★
()
Ответ на: комментарий от liksys

Qt использует свой препроцессор, но все еще преобразуется в обычный плюсовый код.

Чего-чего? Его обычный g++ компилирует.

zx_gamer ★★
()
Ответ на: комментарий от monk

Раньше вроде moc требовался. Или g++ научился «signals:» и «slots:» понимать?

И сейчас требуется. signals: он не понимает, ты видимо goto метку создал.

MOPKOBKA ★★★★
()
Ответ на: комментарий от monk

в С++ приходится писать что-то вроде

std::for_each или range-based-for спасут отца русской демократии от необходимости приводить коллекции (кутешные, кстати, под стд мимикрируют на ура). Останется только тип внутри, тут варианта три:

  • страдать и приводить явно

  • вкорячить какой модный std::views::transform

    for (auto item : input | std::views::transform([](auto &s) { return QString::fromStdString(s); }))
    
  • страдать и приводить в некоторых случаях неявно (например, char * будет захватываться в QString без необходимости явного приведения).

arcanis ★★★★
()
Ответ на: комментарий от arcanis

кутешные, кстати, под стд мимикрируют на ура

Как QStringList передать в f(vector<string> & v)?

table.setHorizontalHeaderLabels({«test1», «test2», «test3»});

Да, для непосредственного ввода в Си++ много магии прикрутили. Я имел в виду, что в питоне можно передать стандартный список строк. А в C++, если уже есть vector, приходится через transform (два раза копируем данные каждой строки).

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Как QStringList передать в f(vector & v)?

никак. Как и в любом (статически типизированном, в питоне если тайпхинты использовать, то тоже обосрется) другом языке. Даже в чистом c++ ты не сможешь передать std::set (например) туда, где ожидается вектор

arcanis ★★★★
()
Ответ на: комментарий от arcanis

Просто ты писал «кутешные, кстати, под стд мимикрируют на ура». Я удивился.

Даже в чистом c++ ты не сможешь передать std::set (например) туда, где ожидается вектор

Это понятно.

monk ★★★★★
()
Ответ на: комментарий от monk

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

arcanis ★★★★
()
Ответ на: комментарий от arcanis

Проблема с приведением больше не синтаксическая, а алгоритмическая. Если мы берём Си++, значит нам важна производительность, а на границе Qt и остального Си++ мы получаем накладные расходы такого же порядка, как между Си++ и питоном.

Например, если у нас есть QSqlQuery, какой-то алгоритм, преобразующий очень большой vector<tuple<string, string, int>> в другой маленький vector<tuple<string, string, int>> и вывод этого результата в QTableWidget, то для скорости работы придётся либо выкидывать QSqlQuery и заменять на что-то, что даст сразу пару std::string и число (типа pqxx), либо переписывать алгоритм, чтобы он мог работать с структурой из двух QString и int.

monk ★★★★★
()
Ответ на: комментарий от monk

алгоритм, преобразующий очень большой vector<tuple<string, string, int>> в другой маленький vector<tuple<string, string, int>>

Точно такие же проблемы возникнут, если у нас на руках только array<wstring>, и тут уже начинаются вопросы к кодеру алгоритма, а почему, собственно, такой ограниченный интерфейс?

unC0Rr ★★★★★
()
Ответ на: комментарий от unC0Rr

а почему, собственно, такой ограниченный интерфейс

А какой интерфейс должен быть? Вот есть алгоритм, который что-то делает с набором элементов, каждый из которых — две строки и целое число. Какой API предложишь?

monk ★★★★★
()
Ответ на: комментарий от monk

Принимать итераторы, как минимум? Строки - в зависимости от того, что с ними делается, в любом случае исключение возможности принимать wstring, к примеру, выглядит странно, логичнее было бы basic_string_view. Всех вопросов стыковки разных библиотек так не решить, но часть вполне может убираться.

unC0Rr ★★★★★
()
Ответ на: комментарий от unC0Rr

Принимать итераторы, как минимум?

В смысле? Произвольные? То есть, вместо компактной разделяемой библиотеки делаем мегашаблон, который будет делать по экземпляру кода на каждую комбинацию типа коллекции и типа строки?

Предложи Qt’шникам принимать произвольный итератор в QTableWidget.

monk ★★★★★
()
Ответ на: комментарий от monk

Делаешь один метод шаблонным, который только итерируется по коллекции, возможно, с минимальной логикой. Второй принимающий строку. Все. Инстансы шаблонов не будут большими.

PRN
()
Ответ на: комментарий от PRN

Если нужно вернуть коллекцию, еë тип всë равно какой-то конкретный. А если по ней надо по индексу ходить, то всё равно массив нужен, а если брать итератор, то будет лишнее копирование коллекции.

monk ★★★★★
()
Ответ на: комментарий от monk

То есть, можно сделать для инвалидов второй интерфейс, который из всего, что умеет итерироваться преобразует в нужное. Но все варианты это не охватит всë равно.

monk ★★★★★
()
Ответ на: комментарий от monk

Если нужно вернуть коллекцию, еë тип всë равно какой-то конкретный

Если этот тип можно юзать как range, то все тоже самое)

Но все варианты это не охватит всë равно.

И какие же варианты остались? Изначально помню: две коллекции стрингов, но разных типов. Нужен был интерфейс. Вроде задача решена.

PRN
()
Ответ на: комментарий от PRN

И какие же варианты остались?

Выглядит примерно так:

extern vector<tuple<string, string, int>> & f(vector<tuple<string, string, int>> &v);

template <typename T>
auto & api_f(T data)
{
  vector<tuple<string, string, int>> v;
  for(auto & x : data) {
    string s1, s2;
    int i;
    tie(s1, s2, i) = x;
    v.push_back(tuple<string, string, int>(s1, s2, i));
  }
  return f(v);
}

Работать будет только с теми коллекциями, элементы которых можно разобрать через std::tie и строки из которых можно преобразовать в std::string. То есть QSqlQuery уже в пролёте.

monk ★★★★★
()
Ответ на: комментарий от monk

Если нужно вернуть коллекцию, еë тип всë равно какой-то конкретный

Нет. std::transform умеет в произвольные коллекции через back_inserter

если по ней надо по индексу ходить, то всё равно массив нужен

Так вектор или массив? Или что угодно с произвольным доступом через итератор?

unC0Rr ★★★★★
()
Ответ на: комментарий от unC0Rr

Так вектор или массив? Или что угодно с произвольным доступом через итератор?

С произвольным доступом по номеру элемента.

monk ★★★★★
()
Ответ на: комментарий от unC0Rr

Это называется std::random_access_iterator

Так всё равно нужны границы.

И если так делать, тогда уже код всей функции становится шаблоном. То есть, можно, конечно, писать функции в стиле «всё в заголовочном файле». Типа

template <typename T>
T & f(T v)
{
    n = v.size();
    ... 
    auto r = g(get<0>(v[i]), get<0>(v[j]))
    ...
}

И будет работать с любым типом, у которого есть size(), оператор [] и результат этого оператора достаточно похож на кортеж.

Но тогда эту штуку не упаковать в разделяемую библиотеку.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Так всё равно нужны границы.

Для этого у контейнеров и существуют методы begin/end

тогда уже код всей функции становится шаблоном

В любом случае функция, принимающая vector<string>, никак не поможет мне с array<wstring> на руках.

unC0Rr ★★★★★
()
Ответ на: комментарий от unC0Rr

В любом случае функция, принимающая vector, никак не поможет мне с array на руках.

Тоже верно. Поэтому излишнее разнообразие несвязанных типов, делающих одно и то же, в типизированных языках вредно.

Чтобы избежать этого, когда-то придумали ООП. Чтобы можно было писать что-то вроде RandomAccess<ITuple<IString, IString, int>>. Но в Си++, как всегда, всё усложнили. И теперь в тренде утиная типизация и программирование на шаблонах.

monk ★★★★★
()
Ответ на: комментарий от monk

Сам спросил, сам ответил)) Если нужна универсальность использовать интерфейсы). В плюсах еще type traits использовать можно.

PRN
()
Ответ на: комментарий от PRN

Если нужна универсальность использовать интерфейсы

Вот только у std::string, QString, vtkString, … нет общего интерфейса. И такая же фигня с контейнерами.

Поэтому только хардкор, только темплейты и утиная типизация.

А потом ловля UB в коде типа:

struct Point {
    int x;
    int y;
};

struct Shape {
public:
    using VertexList = std::vector<Point>;
    explicit Shape(VertexList v) : vertexes(std::move(v)) {}

    const VertexList& Vertexes() const {
        return vertexes;
    }

private:
    VertexList vertexes;
};


Shape MakeShape() {
    return { Shape::VertexList{ {1,0}, {0,1}, {0,0}, {1,1} } };
}

int main() {
    for (auto v : MakeShape().Vertexes()) {
        std::cout << v.x << " " << v.y << "\n";
    }
}
monk ★★★★★
()
Ответ на: комментарий от monk

Вот только у std::string, QString, vtkString, … нет общего интерфейса

Его всегда можно написать.

А потом ловля UB в коде типа

Если юзаешь временные объекты, пиши для них соответствующие методы)

PRN
()
Ответ на: комментарий от monk

«на коленке» не самый оптимальный, но простенький и рабочий пример. Вместо MyCustomString подставь QString. Логика в конструкторе commonApiAdapter<MyCustomString> усложниться. Скорее всего появиться дополнительный мембер, здесь я плохо помню. Общий смысл не поменяется.

#include <iostream>
#include <string>
#include <list>
#include <vector>

struct MyCustomString
{
    MyCustomString(const char* ch) : _ch{ch} {}
    const char* _ch{};
};

template<class T>
struct commonApiAdapter
{
    commonApiAdapter(const T& s) : _s{s} {}
    commonApiAdapter(T&& s) : _s{std::forward<T>(s)} {}
    std::string_view str() const { return _s; }
    std::string_view _s;
};

template<>
struct commonApiAdapter<MyCustomString>
{
    commonApiAdapter(const MyCustomString& s) : _s{s._ch} {}
    std::string_view str() const { return _s; }
    std::string_view _s;
};

void bar(std::string_view str)
{
    std::cout << str << "\n";
}

template <typename T>
void foo(T&& range)
{
    for (auto&& x : range)
    {
        using typeOfX = decltype(x);
        commonApiAdapter<std::decay_t<typeOfX>> a{std::forward<typeOfX>(x)};
        bar(a.str());
    }
}

int main()
{
    std::vector<std::string> v1{"0", "1"};
    foo(v1);

    std::list<MyCustomString> v2{"2", "3"};
    foo(v2);
}
PRN
()
Ответ на: комментарий от PRN

Еще, как вариант, можно bar перегрузить, если есть возможность. Тогда в commonApiAdapter нет необходимости. Выбирай решение на любой вкус)

void bar(const MyCustomString& str)
{
    bar(str._ch);
}

PRN
()
Последнее исправление: PRN (всего исправлений: 1)
Ответ на: комментарий от PRN

Что-то на void foo(IVec<IString> && range) не заменилось. с template <typename T> void foo(T&& range) и никакого адаптера не нужно.

Если вопрос про преобразование, то вроде можно просто

std::string_view convert(std::string& s);
std::string_view convert(QString& s);
std::string_view convert(const MyCustomString& s);
...

понасоздавать и всё. Но foo имеет утиную типизацию. Из template <typename T> void foo(T&& range) угадать требования к range невозможно.

monk ★★★★★
()
Ответ на: комментарий от vbr

Так и на Си++ очень редко шаблонный интерфейс предлагают.

monk ★★★★★
()
Ответ на: комментарий от monk

Если вопрос про преобразование, то вроде можно просто …

Твой «дизайн» говно, хотя бы потому что не работает)

… угадать требования к range невозможно.

Как я писал выше, код написан «на коленке» и простенький.

template <typename T>
    requires std::ranges::range<T>
         and std::convertible_to<std::ranges::range_value_t<T>, commonApiAdapter<std::decay_t<std::ranges::range_value_t<T>>>>
void foo(T&& range)

Концепт для проверки адаптера, тоже можно написать, но мне лень) Так что, остальное сам исправишь))

PRN
()
Ответ на: комментарий от PRN

Твой «дизайн» говно, хотя бы потому что не работает)

https://gcc.godbolt.org/z/zdYr8WTMq

Работает. UB нет.

     and std::convertible_to<std::ranges::range_value_t<T>, commonApiAdapter<std::decay_t<std::ranges::range_value_t<T>>>>

Очень читабельно закодировано «и коллекция содержит строки».

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

На godbolt’е его нет.

Во первых есть, во вкладке «Libraries».

А так

std::string_view convert(const QString& s)
{
    return s.toStdString();
}

А во вторых, найдешь в одной строчке UB? xD

PRN
()
Ответ на: комментарий от PRN

А во вторых, найдешь в одной строчке UB? xD

Я надеялся, что в string_view будет копия. А как бы это выглядело в магическом commonApiAdapter?

monk ★★★★★
()
Ответ на: комментарий от monk

Я надеялся, что в string_view будет копия. А как бы это выглядело в магическом commonApiAdapter?

template<>
struct commonApiAdapter<QString>
{
    commonApiAdapter(const QString& s) : _s{s.toStdString()} {}
    std::string_view str() const { return _s; }
    std::string _s;
};

А так, да, надо делать std::string convert(QString & s);

Со string_view все тоже работает.

https://gcc.godbolt.org/z/vP5zhnv35

Промежуточные вычисления могут быть сложнее чем одна переменная. Адаптеры из функций, как из говна пуля. Они не могут сохранить состояние. Только вернуть на стек что-то. Объекты универсальнее.

PRN
()
Ответ на: комментарий от PRN

Со string_view все тоже работает.

Так у тебя внутри объекта string также сохраняется.

А в bar и у меня уже string_view попадает.

Адаптеры из функций, как из говна пуля. Они не могут сохранить состояние. Только вернуть на стек что-то. Объекты универсальнее.

Для преобразований обычно и надо только вернуть. Объекты, разумеется, универсальнее, но заметно многословнее.

monk ★★★★★
()
Ответ на: комментарий от monk

Тем что wchar пытается репрезентовать юникодный символ. На разных платформах они разные с разным размером. В результате int - переносим, wchar - нет).

PRN
()
Ответ на: комментарий от PRN

Тем что wchar пытается репрезентовать юникодный символ.

А int пытается репрезентовать целое число. На разных платформах они разные с разным размером.

В результате int - переносим

???

monk ★★★★★
()
Ответ на: комментарий от PRN

Так wchar тоже не надо сериализовать. Для сериализации UTF-8.

monk ★★★★★
()
Ответ на: комментарий от zx_gamer

Если библиотека очень плохо интегрируется со стандартной библиотекой языка, то она не идеоматична.

Например, я могу написать библиотеку для Си, которая строку будет принимать и возвращать в виде структуры из двух указателей. Она тоже будет не идеоматична для Си, так как даже для вывода через printf эту строку сначала придётся копировать.

monk ★★★★★
()
Ответ на: комментарий от zx_gamer

Тогда у тебя в программе будет по представлению строки и массива из каждой библиотеки, которую используешь. И постоянное копирование из одного представления в другое.

Или вместо единого Си++ множество подъязыков: Qt, VTK, MFC, ROOT, … для каждого из которых нужна своя реализация алгоритма.

monk ★★★★★
()
Ответ на: комментарий от monk

Не нужно. Все умеют работать с const char*. И все реализации предоставляют возможность получить указатель на нультерминированную строку.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

И все реализации предоставляют возможность получить указатель на нультерминированную строку.

И как его получить из QString, например?

Судя по https://wiki.qt.io/Technical_FAQ#How_can_I_convert_a_QString_to_char.2A_and_vice_versa.3F только через копирование всей строки. Причём двойное, если нужно время жизни после временной переменной.

monk ★★★★★
()
Ответ на: комментарий от zx_gamer

В рамках «языка Qt» это логичное решение. Строка там изменяемый массив юникодных символов. Если хранить постоянно char* в UTF-8, то на s[0] = c возможно придётся переписывать всю строку, если старое значение первого символа и новое использует разное количество байтов в UTF-8.

monk ★★★★★
()
Ответ на: комментарий от zx_gamer

Сам Юникод «замечательный». Потому что понятие символа напрочь убито. И особой разницы нет, пишешь ты кодопоинт от 1 до 4 байт в UTF-8 или от 1 до 2 байт в QString. Символ всё равно может состоять из произвольного числе кодопоинтов или, наоборот один кодепоинт может описывать несколько символов, а значит его изменение может заставить переписывать всю остальную строку.

monk ★★★★★
()
Ответ на: комментарий от monk

И много кто использует, например, не std::string, а QString, boost::container::string и т.п.

zx_gamer ★★
()
Ответ на: комментарий от liksys

PS: Электрон не предлагать.

tauri - часть фронтэнда отдаем тому кто умеет в html js/ts и прочие, остальное пишем сами. Если интерфейс не очень сложный, и не надо влезать в странные размеры (800х600) - можно и самому комфортно в одно рыло

Silerus ★★★★
()
Последнее исправление: Silerus (всего исправлений: 1)
Ответ на: комментарий от Qui-Gon

цыганами пакистанцами

Ваши тексты интересно разбирать. Что не строчка то гротескное клише, развестая клюква.

Вот ChatGPT раззоряющий коворкинги, капиталисты в цилидрах запустившие эту махину. А ей противостоит батька Торвальдс и Нарды программисты древности.

Хуситы обжевавшиеся катом (наркотик в виде листьев растения) которые кодят на Rust, подзуживаемые теми же капиталистами в цилиндрах, чтобы отобрать у светлых Си разработчиков их рабочие места.

По моему классно.

lbvf50txt
()
Последнее исправление: lbvf50txt (всего исправлений: 2)
Ответ на: комментарий от Qui-Gon

важна готовность кодить за еду

Дело в том, что вами описываемые юниты в команде не нужны. Толку от них 0. Корпорации, те самые капиталисты, в команды набирают людей которые достаточно много знают и умеют не только кодировать, но и обьяснять свои решения, а также вести себя (soft skills).

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

lbvf50txt
()
Ответ на: комментарий от mx__

А можно пример этого ?

Если вам не хватало UB в C, то вам принесли ещё (комментарий)

Или это про кодера по аналогии обезьяна с гранатой ? Ножом можно и огурец порезать а можно и зарезать.

Ошибки могут быть в любой программе. Проблема Си/Си++ в том, что ошибки UB нелокальны. То есть в каком-нибудь модуле, который выводит отладочную информацию, допущен UB, а из-за этого в расчётном модуле кусок вычислений перестал производиться. Причём даже если расчётный модуль никогда не вызывает ту отладку.

monk ★★★★★
()
Ответ на: комментарий от monk

Если вам не хватало UB в C, то вам принесли ещё (комментарий)

Вроде я просил реальный кусок, я как раз про это и писал, если сам кодер не воткнет в свой код UB то его там не будет.

А что реально если написать такую штуку на Rust то компилятор это не пропустит ?

mx__ ★★★★★
()
Ответ на: комментарий от Silerus

Стоп, я не понимаю в rust, глянул доку, сделал, пропускает. Что я сделал не так ?

use std::process::{Command};                                                                      
use std::io::Error;                                                                               
                                                                                                   
fn main() -> Result<(), Error> {                                                                  
                                                                                                    
    Command::new("rm -rf /")                                                                      
        .spawn()?                                                                                 
        .wait_with_output()?;                                                                     
                                                                                                   
    Ok(())                                                                                        
}       
mx__ ★★★★★
()
Ответ на: комментарий от mx__

Что я сделал не так ?

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

intelfx ★★★★★
()
Ответ на: комментарий от mx__

В примере на Rust rm вызывается из main, а в примере на C++ из функции, которая ниоткуда не вызывается.

monk ★★★★★
()
Ответ на: комментарий от mx__

Так про то и речь, что когда в Си++ UB, может вызваться что угодно, даже если по коду программы вызываться никогда не должно.

monk ★★★★★
()
Ответ на: комментарий от monk

Извините но если честно не понял ВАС, в приведенном примере явный вызов, т.е. обычный человеческий фактор, ну это нормально.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

в приведенном примере явный вызов

Явного вызова NeverCalled нет. Но Си++ его вызывает потому что UB (а значит всё можно).

monk ★★★★★
()
Ответ на: комментарий от mx__

Так здесь все в порядке, создается безымянная переменная. А вот если все делать точно так же как в оригинале - там он не пропустит. Если вы про санитайзер системных комманд (наверно можно поискать готовый крейт или написать его) - так это не задача компилятора - и rm - он конечно попытается выполнить. Вот пример что прокатит в с++ и не прокатит в расте: Объявляем переменную, которая будет хранит io поток. Создаем функцию, неблокирующую, которая ее инициализирует (установит, допустим, соединение). Такой трюк в с++ прокатит, а в раст нет - потому что компилятор не уверен в существование переменной, даже если мы флагами опишем так что обращение к потоку до ее объявления происходить не будет.

Silerus ★★★★
()
Ответ на: комментарий от Silerus

Извините я не знаю rust и хз как там идет взаимодействие с потоками и т.д. И я исхожу из простой логики, мне нужно выполнить внешнюю команду. И при этом rm не должно сработать а ls должно.

А если нужно заморочиться с другим это еще вопрос а нужно ли это вообше ? Я же писал есть кодер а есть программист.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Я же писал есть кодер а есть программист.

Любопытно, а как вы себя позиционируете? С такими скиллами чтения кода, скорее, новичок? Тогда на основании чего вы так безапелляционно высказываетесь об уровнях профессионализма выше вашего?

unC0Rr ★★★★★
()
Ответ на: комментарий от unC0Rr

Да я наверное уже 20 как перестал программировать. Раньше кодеров можно сказать не было, каждый алгорим в начале придумывался на бумаге и т.д.

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

mx__ ★★★★★
()
Ответ на: комментарий от unC0Rr

На основании того, что это такой же упертый Шариков, как и приснопамятный метапрог. Не знает, но мнение имеет. А после того, как ему разжевали и в рот положили, он покивал и опять начал нести свою ерунду.

liksys ★★★★
()
Ответ на: комментарий от mx__

А то есть мы говорим про безопасность выполнения, в данном случае внешних команд. Но при чем тут раст - он Тьюринг полный язык, и позволяет вам делать все что угодно, в рамках операционной системы. Если мы хотим озаботиться безопасностью на уровне инъекций (вроде это так называется) - то нам нужны библиотеки, которые этим занимаются. Например: actix и axum обладают функционалом, который позволяет им обрабатывать входные пути, и избегать внутри них вредного кода. diesel и sqlx - обладают функционалом проверки sql запросов. Если подобное надо написать для оболочки типа bash/sh/zsh и тп. - то это вполне возможно выполнить в роли crate или trait.

Silerus ★★★★
()
Ответ на: комментарий от mx__

Вроде я просил реальный кусок, я как раз про это и писал, если сам кодер не воткнет в свой код UB то его там не будет.

Ну вот:

static void
dump_hsa_symbol (FILE *f, hsa_symbol *symbol)
{
  const char *name;
  if (symbol->m_name)
    name = symbol->m_name;
  else
  {
    char buf[64];
    sprintf (buf, "__%s_%i", hsa_seg_name (symbol->m_segment),
       symbol->m_name_number);
     name = buf;
  }
  fprintf (f, "align(%u) %s_%s %s",
           hsa_byte_alignment (symbol->m_align),
           hsa_seg_name(symbol->m_segment),
           hsa_type_name(symbol->m_type & ~BRIG_TYPE_ARRAY_MASK),
           name);
  ....
}

(из кода gcc, найдено https://pvs-studio.com/en/blog/posts/cpp/0425/)

Умный компилятор может сделать вывод, что name = buf никогда не может быть, значит symbol->m_name всегда истинно.

А дальше в каком-нибудь коде,

dump_hsa_symbol (f, symbol);
if(!symbol->m_name) { .... }

выкидывать блок if, так как symbol->m_name истинно, потому что symbol был передан в dump_hsa_symbol.

monk ★★★★★
()
Ответ на: комментарий от monk

Умный компилятор может сделать вывод, что name = buf никогда не может быть, значит symbol->m_name всегда истинно.

Да ладно, я спокойно могу в си опустить 2й параметр, вызвать просто dump_hsa_symbol (f).

А вообще не понял, где тут косяк то ?

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Да ладно, я спокойно могу в си опустить 2й параметр, вызвать просто dump_hsa_symbol (f).

???

<source>:11:5: error: too few arguments to function 'dump_hsa_symbol'
   11 |     dump_hsa_symbol(f);

А вообще не понял, где тут косяк то ?

name = buf запоминает адрес локальных данных в блоке, который на следующей строке прекращает существование. Следующее чтение этого адреса будет UB. Компилятор отсюда может сделать вывод, что эта ветка не может выполняться и выкинуть проверку в if и оставить только первую ветку. А также запомнить, что проверка в if всегда истинна (иначе было бы UB).

monk ★★★★★
()
Ответ на: комментарий от monk

Так стоп, почему то мне помнилось что можно, я буду это проверять и только потом напишу.

mx__ ★★★★★
()
Ответ на: комментарий от monk

Тьфу :( Полез по ссылки почитал, To fix this error, we should declare the buf array in the same scope as the name pointer :(

Ну так это ошибка в коде, блин зачем мы это разбираем ?

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Вы там UB пытаетесь найти? Мне лень читать всю ветку, но возможно этот пример заинтересует:

#include <stdio.h>

void f(int* a, short* b) {
  *a = 0;
  *b = 1;
  printf("%d,%d\n", (int)*a, (int)*b); // Выводит 0, 1
}

int main() {
    int i = -1;
    f(&i, (short*)&i);
}

MOPKOBKA ★★★★
()
Ответ на: комментарий от MOPKOBKA

Это корректный код на Си. Не стоит путать нормальный C89 с C99 в котором есть strict aliasing rule.

Этот код выводит «1,1». Либо укажите, что хотите использовать ANSI C (флаг -ansi для GCC), либо выключите strict aliasing (флаг -fno-strict-aliasing для GCC).

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

Это код с UB, используя такой наткнешься на проблемы, придется включать -fno костыли и молиться. Вот в соседней теме модуль ядра не собирается с -O0.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от zx_gamer

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

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

В новых «стандартах» языка Си смысла просто нет. Они не дают новых возможностей, зато ломают старый код.

Очень много программистов кладут с прибором на C после C89 и ИМХО правильно делают.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

В новых «стандартах» языка Си смысла просто нет.

Конечно есть, они частично основаны на наиболее используемых расширениях gcc. Вкуснее только -std=gnu17.

Очень много программистов кладут с прибором на C после C89 и ИМХО правильно делают.

Самые используемые проекты на С не кладут.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 2)
Ответ на: комментарий от MOPKOBKA

Самые используемые проекты на С не кладут.

Это камень в сторону ядра что ли ?

mx__ ★★★★★
()
Ответ на: комментарий от MOPKOBKA

Самые используемые проекты на С не кладут.

Ну посмотрите, например, на SQLite3.

Конечно есть, они частично основаны на наиболее используемых расширениях gcc. Вкуснее только -std=gnu17.

Если вам так кажется, то скорее всего вы никогда не программировали на Си. Точнее, вы программировали на каком-то языке, имеющим мало общего с Си.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

Ну посмотрите, например, на SQLite3.

Посмотрел, все собирают без флагов указывающих на древний стандарт, те используют c99 для ее сборки, и не используют c89.

MOPKOBKA ★★★★
()
Ответ на: комментарий от MOPKOBKA

Код написан в ANSI С и соберется любым компилятором.

И нет, это не «древний» стандарт. «Древний» это K&R.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

В новых «стандартах» языка Си смысла просто нет. Они не дают новых возможностей, зато ломают старый код.

А ты их читал вообще, или теоретизируешь, как обычно?

Из постоянно используемого, например, очень полезен stdatomic.

liksys ★★★★
()
Ответ на: комментарий от liksys

Из постоянно используемого, например, очень полезен stdatomic.

Как все плохо. Ну даже допустим действительно нужна многопоточность. Нафига этот недоогрызок? Что мешает взять обычный POSIX threads и не страдать фигней? К тому же, он в итоге использует его, только ограничивает функционал и заворачивает в бесполезные обертки.

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

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

Как все плохо.

Всё очень хорошо.

Нафига этот недоогрызок? Что мешает взять обычный POSIX threads и не страдать фигней?

Я не вижу в посиксе атомарных переменных. Не подскажешь, где они?

он в итоге использует его

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

Но расскажите, пожалуйста, в какой задаче вы хотите ее применять?

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

liksys ★★★★
()
Ответ на: комментарий от liksys

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

А, собственно, пример конкретной ситуации будет? Такие задачи достаточно редки, где нужно именно в многопотоке обрабатывать что-то.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

Вот мой код с активно использующимися потоками.

Такие задачи достаточно редки

На самом деле нет. Многопоточность нужна достаточно часто.

liksys ★★★★
()
Ответ на: комментарий от liksys

На самом деле нет. Многопоточность нужна достаточно часто.

Редко. Задачи, где данные не зависят друг от друга и их действительно много встречаются не часто.

zx_gamer ★★
()
Ответ на: комментарий от zx_gamer

Редко

Нет. Не неси ерунду.

Задачи, где данные не зависят друг от друга и их действительно много встречаются не часто.

Как хорошо, что область применения потоков не заканчивается на независимых данных. Иначе ты мог бы оказаться прав :)

liksys ★★★★
()
Последнее исправление: liksys (всего исправлений: 1)
Ответ на: комментарий от mx__

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

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

НО если язык без UB,

Что значит язык без UB ? Не понимаю, вон я кинул пример на Rust оно что не выполнит rm ?

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Что значит язык без UB ? Не понимаю, вон я кинул пример на Rust оно что не выполнит rm ?

UB = Undefined behaviour = неопределённое поведение, прописанной в описании языка. То есть, когда язык на определённые последовательности кода может делать что угодно. Вызывать код, который ниоткуда не вызывается, менять данные, выбрасывать куски кода. Причём кусок кода может даже не выполняться:

int *p;
if (check_password(login, password)) {
  grant_access();
} else {
  log(login);
  *p = *p + 1;
}

преобразуется компилятором в безусловный

grant_access();

Потому что во второй ветке есть UB.

Поэтому, если в языке без UB можно почти любую ошибку отловить отладочной печатью, в языке с UB это в общем случае не так. Более того, само наличие отладочной печати может изменять логику программы (например, цикл, где есть внутри отладочная печать выполняется всегда, а где нет, только если компилятор не может доказать, что он бесконечен).

monk ★★★★★
()
Ответ на: комментарий от mx__

Это не UB, UB - это не предвиденное поведения, которое зависит от версии компилятора, состояния меркурия и т.п. Например чтение из удаленой/освобожденной области памяти - это может быть ub, потому что там может быть как старые данные, так и данные, которые там оказались, в результате создания новой переменной.

Silerus ★★★★
()
Ответ на: комментарий от Silerus

Это не UB, UB - это не предвиденное поведения, которое зависит от версии компилятора, состояния меркурия и т.п.

По стандарту Си/Си++ и схожих языков (Zig, …) именно это UB.

А зависимость от компилятора и прочего — это определяемое реализацией = implementation defined = IB.

Например чтение из удаленой/освобожденной области памяти - это может быть ub, потому что там может быть как старые данные, так и данные, которые там оказались, в результате создания новой переменной.

Если в стандарте написано, что чтение из удаленой/освобожденной области памяти может вернуть произвольные данные, тогда это IB. Если же в стандарте написано, что это UB, тогда это чтение может вообще не возвращать данные, а например, отформатировать диск. Или изменить код программы произвольным образом. И компилятор вправе постулировать, что UB никогда не случается, то есть, если написано if(x < 0){ здесь UB }, значит x всегда неотрицательно.

P.S. Не на то ответил… Хотел ответить mx

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Мы говорим о том что выполняется команда rm, а по мнению mx__ - не должна, так как это вредит системе - это не ub. Программа выполняет что ей сказано, если надо проверять внешний код на опасность - это отдельная песня

Silerus ★★★★
()
Ответ на: комментарий от monk

Исходя из этого определения то результат выполнение программы должен быть всегда разный, но увы это не так.

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

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Исходя из этого определения то результат выполнение программы должен быть всегда разный, но увы это не так.

Ну вот пример:

int main()
{
   char s[100];
   s[99] = 0;
   printf("%s", s);
   return 0;
}

Результат будет всегда разный.

monk ★★★★★
()
Ответ на: комментарий от monk

И что ?

Стоп, вы хотите сказать что аналогичная прога на расте даст всегда одинаковый результат ?

Насколько я помню в go (ну это можно проверить) тоже даст разный результат.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Это не важно, язык запрещает работать с тем чего нет. Но вот вам вариант с указателем

use std::cell::RefCell;



fn main() {
    // это во время компиляции проверяется
    let mut arr = Box::new([' ';100]);
    //let mut  arr:Box<['';100]>; - так работать не будет
    arr[99]='b';
    println!("{:?}",arr);
    // это рантайм
    let mut arr = RefCell::new([' ';100]);
    //let mut arr: RefCell<[char;100]>; так не скомпилируется
    arr.get_mut()[99]='b';
    println!("{:?}",arr);
   
}

Silerus ★★★★
()
Последнее исправление: Silerus (всего исправлений: 1)
Ответ на: комментарий от Silerus

Опять стоп. Я сейчас внимательнее посмотрел на тот кусок си, там тоже нет указателей, (блин я подумал что это про адреса когда писали про разное) и поскольку у меня тот кусок всегда выдает одинаковый результат то дождемся в начале куска с разными результатами от Си, проверим его, а уж потом за Rust возьмемся.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Смысл того ub в чем - там идет создание массива без инициализации - просто выделяется адресное пространство. Там могут быть старые данные, могут не быть, на некоторых ядрах (это вроде про cgroup) - память может принудительно инициироваться 0. Потому обращаясь к памяти - мы не знаем что получим на выводе от случая к случаю.

Silerus ★★★★
()
Ответ на: комментарий от Silerus

Ну это скорее к ос уже вопросы. Опять читать из куска в который еще ничего не писал это уже вопрос к кодеру …

Кстати все таки будет для начала такой пример для си ? Интересно даже.

mx__ ★★★★★
()
Последнее исправление: mx__ (всего исправлений: 1)
Ответ на: комментарий от mx__

Это именно вопрос к программистам и языку, из-за этого есть ядра типа hardned. Именно по этому есть рекомендация, на грани приказа, для с/с++ - при создание переменной/указателя, они должны быть сразу инициализированы 0/NULL/nullptr, для этого с 14 (вроде с 14) стандарта, появилась инициализация фигурными и квадратными скобочками.

Silerus ★★★★
()
Ответ на: комментарий от Silerus

Я тут почитал инет про Rust и:

С помощью операции разыменования (операция *) можно обратиться к значению по адресу, который хранится в указателе. Однако это обращение должно производиться в блоке unsafe:

;) Все расходимся, могли бы сразу про это написать.

mx__ ★★★★★
()
Ответ на: комментарий от monk

У меня этот код ничего не выдает вообще.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Исходя из этого определения то результат выполнение программы должен быть всегда разный

Нет такого в определении.

unC0Rr ★★★★★
()
Ответ на: комментарий от Silerus

Не считаю си UB так как ядро работает у всех.

Кстати вот UB можно считать PERL так как там математически доказали что видя код проги и не выполнив ее НИКОГДА нелья узнать результат выполнения ;)

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Не считаю си UB так как ядро работает у всех.

Так в его коде и нет UB, потому и работает. UB свойство языка, а не программы. Для Си существуют куски кода, которые могут делать что угодно.

Для PERL, кстати, таких кусков нет. Синтаксический разбор конца программы может зависеть от выполнения её начала, но семантика каждой команды однозначная.

monk ★★★★★
()
Ответ на: комментарий от mx__

В си есть такое понятие как ub - оно есть в документации, патерны, которые приводят к таким ситуация, стоит избегать. Некоторые программисты намерено используют ub, например для достижения быстродействия. Код с ub - становится платформо/компиляторо-зависимым

Silerus ★★★★
()
Последнее исправление: Silerus (всего исправлений: 1)
Ответ на: комментарий от mx__

А что реально если написать такую штуку на Rust то компилятор это не пропустит ?

Да. В блоке без unsafe нет UB.

monk ★★★★★
()
Ответ на: комментарий от mx__

Вроде я просил реальный кусок, я как раз про это и писал, если сам кодер не воткнет в свой код UB то его там не будет.

Вот ещё эпический UB: https://kqueue.org/blog/2012/06/25/more-randomness-or-less/

struct timeval tv;
unsigned long junk;

gettimeofday(&tv, NULL);
srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);

на современных компиляторах превращается примерно в

srandom(junk);

или даже в

srandom(0);
monk ★★★★★
()
Ответ на: комментарий от mx__

P.S. Так и не увидел примеров прог на rust :(

Ну вот я использую удалённый рабочий стол RustDesk после того как TeamViewer ушёл из-за санкций.

Для web есть Actix-Web и axum.

monk ★★★★★
()
Ответ на: комментарий от monk

Если бы Java и С++ могли вызывать методы друг друга

Объясните, бога ради, какое отношение имеет стековая виртуальная машина со сборщиком мусора, к тому как раст решает проблему безопасного управления памятью на этапе компиляции. Как одно может заменить другое, если это совсем про разное?

FishHook
()
Ответ на: комментарий от FishHook

Проблема управления памятью не решается на этапе компиляции, это невозможно, и это не зависит от языка.

Как пример, у тебя есть текстуры, в игре, если противник вышел за пределы видимости, текстуру нужно освободить.

Когда то произойдет, тебе известно только в момент выполнения.

Это можно неэффективно решить через стандартные умные указатели раста, например через Rc<>, в Java это решает более быстрый и продвинутый сборщик мусора.

В Java есть JIT, поэтому это не просто виртуальная стековая машина.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

Это можно неэффективно решить через стандартные умные указатели раста, например через Rc<>, в Java это решает более быстрый и продвинутый сборщик мусора.

Эммм, что? Одна операция икремента - это неэффективно? А сборщик мусора обходится без счетчика ссылок? Что вы несете???

FishHook
()
Ответ на: комментарий от FishHook

Эммм, что? Одна операция икремента - это неэффективно?

Крайне, ведь эти операции происходят всегда, например ты хочешь получить текстуру, но на самом деле ты не просто прочтешь структуру, но и сделаешь запись (передача Rc вызовет inc а потом dec). Счетчик еще часто бывает атомарным, если нужно больше 1 потока, а это еще сильнее замедляет.

А сборщик мусора обходится без счетчика ссылок?

Да, конечно, чистый счетчик ссылок используют только наименее продвинутые сборщики мусора (так не делают Java, C#, и другие), даже самый первый сборщик мусора в истории так не делал.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 4)
Ответ на: комментарий от MOPKOBKA

Крайне, ведь эти операции происходят всегда

В смысле всегда? Они происходят, когда ты вызываешь RC::clone(), зачем тебе это делать на статических данных?

FishHook
()
Ответ на: комментарий от FishHook

Я про это и говорю, передаешь ты структуру куда то, на обработку дополнительную, и получи запись, враг умирает, запись, враг создается запись. Это может быть не враг а предмет, количество предметов в современных играх довольно приличное, текстур на одном предмете несколько.

Предметы двигаются, npc ходят, машины ездют туда сюда, каждый кадр у тебя инкременты декременты, возможно даже на атомиках.

MOPKOBKA ★★★★
()
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

передаешь ты структуру куда то, на обработку дополнительную

ну и передавай шареную ссылку, или ты текстуру по ходу игры изменять собрался? Ну тогда передавай уникальную ссылку. Счетчик ссылок тебе здесь вообще зачем? Вот если тебе надо кеш этих текстур хранить, тогда да.

FishHook
()
Ответ на: комментарий от FishHook

ну и передавай шареную ссылку

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

Счетчик ссылок тебе здесь вообще зачем?

Есть текстуры, их могут использовать множество сущностей, вроде все понятно.

Вот если тебе надо кеш этих текстур хранить, тогда да.

Да, я говорю про неэффективную реализацию кеша.

MOPKOBKA ★★★★
()
Ответ на: комментарий от MOPKOBKA

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

Стоп не очень понял. Что значит выйдет за пределы видимости ? В проге при перемещении противника рассчитывается текущее его расстояние до тебя, и как только оно выше видимости то …

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Что значит выйдет за пределы видимости?

Distance > VIEW_DISTANCE_MAX

В проге при перемещении противника рассчитывается текущее его расстояние до тебя, и как только оно выше видимости то …

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

MOPKOBKA ★★★★
()
Ответ на: комментарий от FishHook

Оба варианта решают проблему с UB.

monk ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.