LINUX.ORG.RU

GSoap и современный C++

 , gsoap,


0

3

Реально эту штуку заставить генерировать код хотя бы на C++11 чтобы не void*, а std::unique_ptr и так далее было? Ну и хоть кто-то по-человечески с объявлением функций, дабы это всё не выглядело как обертка на С.

Современный C++ мало кто знает и использует из пишущих на C++… Почему это тебя так волнует?

Ты понимаешь, многие из тех, кто пишет на C++ реальный код для реальных проектов, кто хвалит C++, например, в глаза не видели концептов, избегают шаблонов и не очень-то понимают подводных камней семантики перемещения. Стараются, вообще, не использовать явно перемещение - неявно оно там и так будет через copy elision.

Поэтому не все ли равно, обертка над С или нет? По мне так ничего плохо в обертке нет

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

Это всё хорошо, пока оно памятью протекать не начнет или буфером о char* не поранится. Хотел бы я программировать на С, взял бы его и эту тему не создавал.

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

Поэтому не все ли равно, обертка над С или нет? По мне так ничего плохо в обертке нет

Если генерируемый код проверен годами, то C внутри это скорее хорошо. Единственное, что реально имеет значение — какой API предоставляется для пользователя, а внутри там пусть хоть на одних void* всё будет

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

Это всё хорошо, пока оно памятью протекать не начнет или буфером о char* не поранится

А были такие прецеденты с кодом, который генерит gsoap? Тогда сам gsoap надо дорабатывать, а не костыли городить сверху

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

Поддерживаю.

А что касается std::unique_ptr, там в пользовательском коде исключения возникают?

Просто исключения - очень сложная тема в C++. Большинство недооценивает ее важность, да и просто не понимает. Это же не джава какая-нибудь! Из-за исключений вполне может и протекать в C++, и падать весь код при неверном использовании. Там разные уровни «безопасности» бывают.

Ну, и конечно, банальных утечек тоже нельзя исключать. Valgrind что-нибудь говорит?

P.S. Кстати, тут на маке начал гонять свой пет-прожект. Ох, ё-моё! Не знаю, что делать со thread_local! На винде и линуксе тот же код работает как часы. Замена на __thread пока не помогла. Замена Apple Clang на GCC тоже особо не помогла, хотя чуточку улучшила положение. Возможно, что есть ошибка в моем коде - исключать никак нельзя. Даже скорее всего, что что-то еще не учел.

Что характерно, аналогичный код на rust работает как часы везде - и на маке, и на винде, и на линуксе. Зря многие набрасываются на rust. Так помучаешься, помучаешься с C++, половишь сегфолты, да и плюнешь на все и начнешь переходить на более простой язык, каким безусловно является rust.

Когда писал на rust, то valgrind запускал всего-то раза два или три. Когда стал переписывать на C++ тот же самый код, то заколебался запускать valgrind и оптимизировать, чтобы догнать по скорости исполнения свой же код на rust. Это, конечно, многое говорит о моих навыках, но вроде бы далеко не самый последний программист на C++.

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

Что еще отмечу, на rust получилось с первой попытки написать быстрый код, причем используя идиоматические конструкции rust. А вот на C++ я намаялся, как же намаялся догонять rust! Например, пришлось отказаться от std::variant и std::function в пользу самописного

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

Ну, и конечно, банальных утечек тоже нельзя исключать. Valgrind что-нибудь говорит?

Говорил, пока на смарт-пойнтеры не переписал. Вот и думай теперь: 2025 год на дворе, а тулза генерит код как в двухтысячном. Против самого Руста ничего не имею, но перейти не вариант пока.

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

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

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

Многие проблемы управления памятью возникают из-за того, что эту задачу C++ никак не решает и он здесь вовсе не причём

Ну как не решает. Пытается решать, но получается не полностью и криво. Как и со всеми другими задачами, которые пытается решать C++.

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

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

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

я не нашел ни одного упоминания gsoap вне onvif.

gSOAP is a C and C++ software development toolkit for SOAP/XML web services and generic XML data bindings

А SOAP много где используется, в том же UPnP, например

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

не очень-то понимают подводных камней семантики перемещения

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

любой std::move на самом деле нужно сопровождать мощным комментом - а почему он тут вообще стоит. потому что его тут легальность очень сильно зависит от контекста.

карочи. если std::move написал не гуру, а нуб или мидл - его надо допросить с пристрастием, и выяснить, зачем он это сделал.

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

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

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

«замыкание» можно и на си ручками нарисовать, если так уж приспичит.

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

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

Ему полезно разобраться почему многие проекты разработы на Си и как они обходятся без всяких фич C++. Конечно суждение было не о том, что C++ плох. Не полезно микроскоп использовать для забивания гвоздей, но можно.

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

Стоп, а вот мы тебя и поймали! Ты что, с rust совсем не знаком?!

Там перемещение - это основная форма передачи параметров, в отличие от C++. А вот чтобы скопировать, в rust нужно явно вызвать функцию clone, то есть нужны специальные приседания, которые выглядят в коде не очень-то и красиво, которые не хочется просто так писать. И до введения синтаксиса async/await, там в асинхронных вычислениях везде было перемещение, и так оно остается до сих пор, надо полагать.

В rust перемещение - это обычно вызов одного memmove, и все! Никаких деструкторов у перенесенного объекта вызывать не нужно. Никакой фигимотины со специальными флажками заводить не нужно, что объект был перенесен.

И да, в rust исключений почти нет, поэтому перемещение практически всегда значительно эффективнее, чем копирование. А вот в C++ так не всегда, но ты похоже не понимаешь толком, почему тебе не нравится перемещение в С++. Краткий ответ - перемещение в C++ может быть медленным из-за возможных исключений.

Ты меня удивляешь. Как ты можешь критиковать rust на весь ЛОР, если нисколько с языком не знаком! Впрочем, в этом весь ЛОР.

А так, мне просто захотелось перетащить на C++ свою упоротую функциональщину для своего пет-прожекта. Функциональщик я, причем со стажем.

Клиентам такого кода не писал, не боись, не ссы. Клиенты и шаблоны-то с трудом читают. Какое там ФП?!

P.S. Кстати, есть мнение, что одна из причин, почему у программистов получаются медленные программы на С++ - это то, что там копирование идет по умолчанию

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

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

С move не будет никаких проблем, если у тебя адекватная система типов без хитровывертов. Если ты руководствуясь какими-то соображениями сделал так, что половина классов у тебя бросает при перемещении, а вторая половина вообще не перемещаема, то тогда конечно у тебя будут проблемы с мувами. В кодовой базе где не перемещаемы пара уникальных классов, а все остальные объекты noexcept movable и при этом после перемещения остаются в валидном состоянии, мувов можно не бояться, с ними всё будет хорошо.

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

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

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

Там перемещение - это основная форма передачи параметров, в отличие от C++.

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

По значению передают нубы, что не видят разницы.

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

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

some_fun(some_type(10));

тут есть значение some_type(10), адрес которого передается в some_fun. само это значение хранится на стеке вызывающего. фактически это такой код.

{
  some_type ___hidden_value__(10);
  some_fun(__hidden_value__);
}

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

по подходу с «перемещением», можно просто обменять две переменные.

это единственное место, где перемещение достаточно корректно.

в других местах оно может порождать всякие неожиданные эффекты, и я же говорю не про передачу параметров, а про явный std::move.

P.S. Кстати, есть мнение, что одна из причин, почему у программистов получаются медленные программы на С++ - это то, что там копирование идет по умолчанию

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

в расте для дурачков ввели костыль - clone. так он весь в костылях.

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

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

А так, я теперь понял, что с rust ты не знаком, и точка

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

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

Этот пост никак не относится к alysnix.

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

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

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

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

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

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

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

нет конструктора и деструктора класса

Деструкторы есть, трейт drop. Как следствие есть raii, более того, он там по-сути обязательный. Эксепшоны тоже есть - паники, просто предпочтительно обрабатывать ошибки через возвращаемое значение.

Конструкторы по сути тоже есть, просто реализованы как статические функции, но выполняют те же задачи.

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

Это не в нормальном ООП, а в ООП без слежения за временем жизни. Так-то вызов деструктора после move’а абсолютно лишний, просто в плюсах по-другому нельзя. А в расте можно, там drop и не вызывается. И хорошо, к ООП это никакого отношения не имеет.

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

То есть, я прав, что с rust ты не знаком. Изучи! Может быть, тебе понравится.

Возвращаясь к исходной теме, потому я и написал, что многие программирующие на C++ сторонятся семантики move, потому что в С++ она действительно сложная, неоднозначная, и в ней есть подводные камни - затронутые выше про те же исключения.

Вообще, исключения - это такая неоднозначная вещь. Довольно сложная. Слишком много, на что она влияет. Я понимаю, почему в гугле их забанили. Слишком все сложно, хотя кажется просто. Прямо как тонкий лед, хотя когда-то от исключений лет 40 назад просто все тащились, когда они появились в той же Аде.

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

Ладно. Пойду займусь другими делами. Всем хорошего дня!

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

Так-то вызов деструктора после move’а абсолютно лишний

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

пример на псевдокоде

{
  var xx:some_type;
  if (cond) {... move(xx)... }
} //тут конец блока. что делать с переменной xx? она может быть 
перемещена и не перемещена. значит надо иметь признак перемещения, рядом с этой переменной.

с++ по любому будет вызывать деструктор, а раст будет хранить признак, что не надо вызывать этот drop?

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

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

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

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

Ладно. Пойду займусь другими делами. Всем хорошего дня!

Так общение на форуме тоже иногда помогает. Но лучше конечно разработкой заниматься.

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

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

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

это не решается в компайлтайме.

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

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

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

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

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

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

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

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

если есть - покажы.

на с++ я пишу

{
  some_class v(10); ///тут сконструировался обьект v класса some_class параметризованный значением 10.

  return v.some_fun(); //тут возвращаем результат некой функции от v и автоматом уничтожаем v.
}

напиши точный аналог на расте

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

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

Но тут я не уверен, я с растом не настолько хорошо знаком, так что могу врать.

Что касается примера, то там раст просто запретит использовать потенциально перемещённую переменную (и правильно сделает, её использование явный говнокод).

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

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

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

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

Что касается примера, то там раст просто запретит использовать потенциально перемещённую переменную (и правильно сделает, её использование явный говнокод).

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

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

счетчик-то ссылок в расте есть. именно поскольку в компайлтайме в общем сдучае не определишь когда на обьект нет ссылок.

вы просто слишком наивно все понимаете этот раст.

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

где ретурн?. это был просто вложенный блок, а не тело функции.

let v = SomeClass::new(10);

причем тут new? обьект на стеке должен быть

зы… а.. это типа мы так конструктор пишем.

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

то есть заимствующую функцию я не могу вызвать в условном участке???… мама дорогая. я не думал что раст настолько плох.

не верю! как станиславский. не верю и все тут.

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

где ретурн?

Можешь написать, если хочешь (но тогда про ; в конце не забудь). В расте он не обязателен.

причем тут new? обьект на стеке должен быть

На стёке объект или нет определяется тем, как ты его объявляешь. Так же как в сишке и плюсах. А не тем, как ты его инициализируешь.

new - это просто общепринятое название для фабрик(конструкторов). Можешь назвать метод зелебобой и вызвать его.

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

то есть заимствующую функцию я не могу вызвать в условном участке???

Можешь. Ты после условного участка не можешь использовать потенциально перемещённую переменную не переинициализировав её. Что опять же абсолютно правильно, ибо error prone говнокод.

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

Только если его специально создать.

в плюсах нет заимствований, и времени жизни. можно вообще не пользоваться shared_ptr.

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

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

в плюсах нет заимствований, и времени жизни

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

а на расте придется везде, где компилятор тупит

Боюсь, что в таком случае тупит не компилятор. В расте счётчики ссылок нужны ровно в тех же случаях, что и в плюсах.

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

Ты после условного участка не можешь использовать потенциально перемещённую переменную не переинициализировав её

вы явно не понимаете процесс. для данной переменной надо понимать - вызывать ли этот ваш drop, в данной точке кода.

если ее переместили - drop вызывать нельзя. если не переместили - drop вызывать обязательно.

что значит «переинициализировать»? сначала нужно решить, вызывать ли ей дроп перед повторной инициализацией.

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

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

В расте счётчики ссылок нужны ровно в тех же случаях, что и в плюсах.

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

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

а счетчики ссылок это для автоматического управления.

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