Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60

О корректном завершении программ на с++

01.11.2025, 19:49. Показов 7317. Ответов 77
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток,

Изучая книгу Страуструппа "Язык программирования С++. Специальное издание", обратил внимание на следующее утверждение "При вызове exit() не будут вызваны деструкторы локальных переменных во всех функциях вверх по цепочке имевших место функциональных вызовов. Генерация и перехват исключений гарантируют корректное уничтожение локальных объектов. Вызов же exit() не позволяет корректно отработать всем функциям из цепочки вызовов. Поэтому лучше не ломать контекст вызова функций и просто сгенерировать исключение, а вопрос о том, что делать дальше, оставить обработчикам"

Допустим, в моей программе в месте, далеком по цепочке вызовов от main(), возникло событие, означающее что программа штатно закончило свою работу. Означает ли написанное выше что:
1) не стоит использовать библиотечные фукнции std::exit(), std::abort()
2) можно не заморачиваться с "правильным" завершением всех функций из цепочки вызовов, а достаточно сгенерировать исключение throw finish(), например. Разместить обработчик в main() и предусмотреть в нем вызов деструкторов глобальных объектов?

Хотелось бы понять и запомнить как правильно поступать при необходимости завершения сложных программ, от которых зависят в т.ч. другие процессы. Понятно, что простые учебные программы можно завершать как угодно.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.11.2025, 19:49
Ответы с готовыми решениями:

Корректное закрытие программы при завершении работы Windows
Моя программа при старте сворачивается в трей и периодически выполняет определенные операции. Окно...

Корректное завершение работы сокетов
У меня система работает на синхронных сокетах. Для приема данных создается отдельный поток...

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

77
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
03.11.2025, 21:43  [ТС]
Студворк — интернет-сервис помощи студентам
DrOffset, я программирую в Visual Studio. Замеры через std::chrono::steady_clock с выводом результатов в консоль. Запускал и через F5 из VS, и собирал через Ctrl+B, затем копировал файлы на рабочий стол. Запускал с рабочего стола. Результаты одинаковые. Версия может и отладочная, файлы лежат в папке ..\x64\Debug. Но других вроде нет. Если что не так, подскажите как правильно.
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
03.11.2025, 23:19
Цитата Сообщение от ADnD Посмотреть сообщение
Если что не так, подскажите как правильно.
Замерять производительность в Debug - неправильно. Вернее - это неинформативно, в Debug-режиме помимо отсутствия оптимизации содержится еще множество дополнительных проверок, сильно замедляющих работу в угоду диагностическим возможностям.

Переключите сборку на Release. И там делайте замеры.
1
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
03.11.2025, 23:28  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Замерять производительность в Debug - неправильно. Вернее - это неинформативно, в Debug-режиме помимо отсутствия оптимизации содержится еще множество дополнительных проверок, сильно замедляющих работу в угоду диагностическим возможностям.
Переключите сборку на Release. И там делайте замеры.
Спасибо огромное!!!

Сделал замеры так: все версии примерно сравнялись +/- несколько миллисекунд. И char* c isspace(), и char* без оного, и string. Т.е. как и должно быть!

Еще раз благодарю!

З.Ы. посмотрю документацию MSVS по различиям между режимами. Так много информации, и так мало времени ((((
0
1980 / 836 / 115
Регистрация: 01.10.2012
Сообщений: 5,233
Записей в блоге: 2
03.11.2025, 23:39
Цитата Сообщение от ADnD Посмотреть сообщение
Версия может и отладочная, файлы лежат в папке ..\x64\Debug
Значит надо переключиться на Release, проверить установки (оптимизация, либы и др), собрать, и тогда уже мерять. Впрочем и в этом случае такие замеры не внушают доверия (vc компилятор известен как один из самых чмошных)
Цитата Сообщение от ADnD Посмотреть сообщение
Неприятно удивлен падением производительности. Время обработки файла увеличилось с 24 до 34 мс.
Причина в замене этого:
Даже если так - на это стоит идти. Тот код что сейчас замеров не заслуживает - уж слишком мал ф-ционал и слишком уж он "учебный". Подсчет слов, почему isspace? Напр запятая не часть слова, а разделитель слов. Затыкать стандартный/штатный вызов самопалом на том основании что "быстрее" - себе дороже

Добавлено через 1 минуту
Цитата Сообщение от DrOffset Посмотреть сообщение
Переключите сборку на Release.
Опередили
0
03.11.2025, 23:54

Не по теме:

Цитата Сообщение от Igor3D Посмотреть сообщение
Опередили
Еще в сообщении #40.

0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,384
04.11.2025, 11:13
Функция atexit() регистрирует функцию, которая будет выполнена при нормальном завершении работы программы.
Всего может быть зарегистрировано до 32 функций,
которые будут выполнены при завершении работы в порядке обратном порядку регистрации.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void quit(void) {
    if (in != NULL)
        fclose(in);
    if (out != NULL)
        fclose(out);
    //-----------------------   
    short en = 10;
    while (en--) { Beep(4000, 8); Sleep(10); }
}
 
 
//================
//================
int main(void) {
    if (atexit(quit) != 0)
        return 1;
 
    in = fopen("in.txt", "r");
    if (in == NULL)
        return 2;
    out = fopen("out.txt", "w");
    if (out == NULL)
        return 2;
Могу функцию напомнить. Может к месту?
1
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
04.11.2025, 12:16  [ТС]
Цитата Сообщение от Igor3D Посмотреть сообщение
Даже если с первого взгляда такой необходимости нет, она обычно выплывает. Чтобы потом не бегать с \n (что кстати не всегда верно). Общий алгоритм всегда такой: отгрыз строку - обработал - отгрыз следующую и.т.д. пока строки не кончились. Др словами читаем из исходного char* как из файла. Поэтому первой надо писать ф-цию получения строки, напр
C++Скопировано
1
const char * TakeLine( const char *& ioSrc, int * oLen );
Заметим что выгодно иметь и др ф-ции "отгрызания", напр TakeWord
Подскажите пожалуйста, вторым аргументом функции вы предполагаете int* oLen. Я правильно понял, что это будет длина возвращаемой строки?

Цитата Сообщение от Igor3D Посмотреть сообщение
- while с инкрементом в конце цикла здесь явно не удачен, на каждый чих нужно проверять финальный null. Лучше цикл for (счетчик найдем через strlen)
- а нужны ли тут вообще какие-то циклы и пробеги по строке? Не обойтись ли типовыми ф-циями поиска подстроки (типа strstr), пусть они и бегают
Если я правильно понимаю работу с-функций типа strstr, в начале нужно определить длину выделяемой строки, выделить память под создаваемый массив и только после этого вызывать саму функцию. С фиксированными буферами я бы не связывался для программы, обрабатывающей файлы, ведь обработчику может встретиться файл любой конфигурации, например с последовательностью непробельных символов длиной в десятки Мб. Что приведет к переполнению буфера.
К чему я это. Если определять длину выделяемой строки или слова стандартной функцией для с-строк, получится подобное:
C++
1
size_t word_len = std::strchr(isSrc, ' ') - ptr_ch + 1;
А пробельных символов несколько: ' ', '\t', '\n', '\r', '\0' (в данном контексте).

Мне кажется проще определять длину слова (строки с минимальными изменениями фрагмента) с помощью:
C++
1
2
while (!::my_isspace(*ptr_ch++)) word_len++;
word_len++;
Но тогда у меня возникает вопрос, зачем в моей задаче нужны функции в стиле const char *strstr(const char *str, const char *strSearch), если я часть задачи буду решать с помощью while(), а часть с помощью strstr()? Какие преимущества мне даст strstr?

Добавлено через 2 минуты
Цитата Сообщение от Наталья8 Посмотреть сообщение
Могу функцию напомнить. Может к месту?
Читал про такую, но еще не пробовал. Спасибо за подсказку)))
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
04.11.2025, 12:40
Цитата Сообщение от ADnD Посмотреть сообщение
С фиксированными буферами я бы не связывался для программы, обрабатывающей файлы, ведь обработчику может встретиться файл любой конфигурации, например с последовательностью непробельных символов длиной в десятки Мб. Что приведет к переполнению буфера.
Не обязательно читать файл целиком в память, чтобы его обработать. А в случаях, когда файл сильно больше доступной памяти, это и не получится совсем.
0
04.11.2025, 12:56

Не по теме:

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

0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,384
04.11.2025, 13:16
Royal_X,
Насчёт goto я конечно кривой и не правильный (мой кот гавно.)
Но как то я начитался обрывков и goto не пользуюсь... Всегда можно обойти...
А выходить из вложенных циклов,
тогда надо башку включать...
По аварии можно... А можно и без goto.
Достаточно опрокинуть булеву переменную, на которой цикл вертиться.
Или break... Или и то и другое.

C++
1
2
3
4
5
//============================= ВЫПОЛНЕНИЕ =====================================
            AVPacket pkt;
            bool _job(true);
            while (_job) {// << ============================================================== ЦИКЛ
            av_init_packet(&pkt);
C++
1
if (read_from_FIFO(out_fmt_ctx, result_audio, fifo) != 0) { av_packet_unref(&pkt); _job = false; break; }
0
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
04.11.2025, 14:50  [ТС]

Не по теме:

Цитата Сообщение от Royal_X Посмотреть сообщение
ADnD, я бы на твоем месте воспользовался возможностью и попросил бы у DrOffset советов. Он и редко бывает на форуме, так что тебе повезло, не теряй свой шанс. Он один из немногих опытных программистов на форуме, хорошо разбирающийся в ООП.
Cпасибо))
Я почувствовал, что многому могу научиться у DrOffset и Igor3D, поэтому пробую в своей программе все что они пишут и добросовестно выкладываю на форум результаты. Надеюсь не получить по башке за "флуд" и "раздувание темы"



Добавлено через 20 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
Не обязательно читать файл целиком в память, чтобы его обработать. А в случаях, когда файл сильно больше доступной памяти, это и не получится совсем.
Я читаю файл по кускам в массив char ReadBuffer[buffersize], где const DWORD buffersize = 4095

Далее сливал результаты в массив
C++
1
char* sourceTxt = new char[(srcFileData.nFileSizeHigh * MAXDWORD) + srcFileData.nFileSizeLow + 1];
Из вашего комментария понял, что sourceTxt[] лишний, и можно было бы вызывать лексический анализатор сразу к содержимому буфера чтения файла, "по кускам" собирая результат в итоговой структуре. Переделаю программу как Вы посоветовали и посмотрю результат.

Мой вопрос к Igor3D был связан с другим аспектом, а именно с использованием функций обработки с-строк, возвращающих указатель. Я сомневался в их целесообразности из-за необходимости подсчета длин каждой получающейся строки. Теперь, если я смогу ограничиться массивом ReadBuffer[4095], все упростится: я сделаю второй буфер такой же размерности для всех временных строк и третий - для слов. 12 кб памяти не будут сильно "жать карман".

Спасибо!
0
Нарушитель
Эксперт функциональных языков программированияЭксперт С++
6700 / 3113 / 1064
Регистрация: 01.06.2021
Сообщений: 12,024
04.11.2025, 17:12
Цитата Сообщение от Наталья8 Посмотреть сообщение
Насчёт goto
забей. ты даже не понял про что я писал

ADnD, не нравится мне твой сишный стиль. Пиши на современном С++.
1
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
04.11.2025, 17:34
Цитата Сообщение от Royal_X Посмотреть сообщение
ADnD, не нравится мне твой сишный стиль. Пиши на современном С++.
Нельзя вот так взять и писать эффективный код на С++.
Для этого нужно хорошее знание основ, то что раньше было в Си и не только(операторы new, передача аргументов, и много всего прочего).
К этому нужно стремится.

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

Аварийное завершение приложение оправданно лишь в том случае, когда ничего нельзя поделать и штатное завершение неопределенно. Поэтому лучше просто упасть, чем завершится с логами или ещё чем, но удалить пользовательскую базу данных, к примеру, ведь мы не знаем как поведет себя приложение.
Особенно учитывая что исключительная ситуация которую приложение не может обработать, например, в этом самом логгере.
В общем случае, в С++ прикладным разработчикам достаточно системы исключений С++. И вызывать напрямую креш программы(через exit или тем более abort) нет необходимости.

По всему остальному, тут мне нечего делать, с советчиками писать свои велосипеды на char*.

Добавлено через 3 минуты

Не по теме:

Цитата Сообщение от Royal_X Посмотреть сообщение
Насчёт goto
Это дикий оффтоп и вообще непонятно что.
Можно втулить его куда угодно, но это лишь говорит о плохом стиле программирования и нежелания сделать лучше.
Если же говорить про эффективность, да, это хорошо, лишь для низкоуровневого кода. Который довольно редко пишется на С++.
И даже там, он сильно ломает читабельность и поддержку кода.
Никто из готушников не может себя сдержать что бы не нагородить непроходимые огороды.
А учитывая довольно специфичные ограничения goto в С++, то ещё и нехило так шанс накосячить.

0
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
04.11.2025, 17:51  [ТС]

Не по теме:

Цитата Сообщение от Royal_X Посмотреть сообщение
ADnD, не нравится мне твой сишный стиль. Пиши на современном С++.
Много над чем надо работать, стиль в том числе. Сейчас перерабатываю свою учебную программу с учетом всех предложений и замечаний из этой темы. Если будет время и желание ее оценить - буду признателен за обратную связь!

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



Добавлено через 5 минут
Цитата Сообщение от SmallEvil Посмотреть сообщение
Нельзя вот так взять и писать эффективный код на С++.
Для этого нужно хорошее знание основ, то что раньше было в Си и не только(операторы new, передача аргументов, и много всего прочего).
К этому нужно стремится.
Мне уже так говорили, поэтому я и изучаю пошагово: типы данных, указатели, структуры, функции, пространства имен, исключения, раздельная компиляция. И пытаюсь что-то создавать на той базе, которую изучил к данному моменту. Параллельно приходится вникать в смежные темы: win32api, компиляторы, какие-то элементы стандартных библиотек
0
Нарушитель
Эксперт функциональных языков программированияЭксперт С++
6700 / 3113 / 1064
Регистрация: 01.06.2021
Сообщений: 12,024
04.11.2025, 18:14
Цитата Сообщение от SmallEvil Посмотреть сообщение
писать свои велосипеды на char*
вот и я подумал, что ADnD идет по стезям Наталья8, полагая, что чем больше астерисков наклепает, то мол тем лучший код получит. Его код просто кишит этим <cstring>...
Алексей1153 тут намекнул про string_view, но никто не услышал.
Понимаю, что у него там еще WinAPI, который со своей стороны постоянно искушает сишным стилем, но не нужно поддаваться этим искушениям.

Кстати, с возвращением из бана.
0
1980 / 836 / 115
Регистрация: 01.10.2012
Сообщений: 5,233
Записей в блоге: 2
04.11.2025, 18:46
Цитата Сообщение от ADnD Посмотреть сообщение
Если я правильно понимаю работу с-функций типа strstr, в начале нужно определить длину выделяемой строки, выделить память под создаваемый массив и только после этого вызывать саму функцию.
Вы прямо-таки нарываетесь на популярный (грубый) ответ
Учи матчасть!
Если Вы услышали о неизвестной (Вам) ф-ции - сразу же открываете справочник (cppreference) и читаете/знакомитесь. Ф-ция strstr никаких аллокаций не требует. Возвращаемый указатель указывает на символ внутри исходной строки, где начинается искомая подстрока. Правда Вам нужна будет strnstr (с ограничением длины), что там с ней в MSVC - не помню, разберетесь.

Кроме того, парсер который аллоцирует/копирует строки не может претендовать на какую-то скорость, и частенько может быть ускорен "в разы". Что приятно ускоряющему, но не автору оригинала Вызов malloc достаточно дорог по сравнению с пробегами по строке.
Цитата Сообщение от ADnD Посмотреть сообщение
Я читаю файл по кускам в массив char ReadBuffer[buffersize],
Не стоит сейчас нагружать тему еще и этим, получится "все кипит и все сырое". Хотя решение ни для кого не секрет и уже звучало выше: работайте с текстом по строкам
Цитата Сообщение от ADnD Посмотреть сообщение
вторым аргументом функции вы предполагаете int* oLen. Я правильно понял, что это будет длина возвращаемой строки?
Да. Вот у Вас длинная строка с конечным нулем. Сканируете ее пока не найден конец строки. Передвигаете указатель на следующий символ (начало новой строки), возвращаете первоначальный указатель и длину до конца найденной строки.

Теперь со структурированием. Немного помогу, задача не такая уж простая. Главный цикл
C++
1
2
3
4
5
6
7
8
9
10
11
12
enum LCType {
 lc_none,  // the line is not commented
 lc_part,   // partially commented
 lc_full     // fully commented
};
 
while (true) {
 const char * s = TakeLine(src, &len);   
 if (!s) return;
 auto state = ParseLineComment(s, len, insideFlag); 
 ...
}
Свалили содержательную работу в ParseLineComment. Тут тоже цикл, вариантов много, напр
/* text1 */ zzzzxx /* // text2 */ ffff /*
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
LCType ParseLineComment( const char * s, int len, bool insideFlag )
{
 while (len > 0) {
   
// if we're already inside comments (opened by prev lines)
// then we're interested only in "*/"  (comments end)
  if (insideFlag) {
    const char * end = Find(s, len, "*/");  // the Find is a function such as strnstr
    if (!end) return lc_full;   // keep current state
 
    insideFlag = false;
    len -= (end - s) + 2;
    s = end + 2;     // advance to next
    continue;
  }
 
// lookup both comments begin
  const char * lc1 = Find(s, len, "//");  
  const char * lc2 = Find(s, len, "/*");  
 
// check for no any comment begin
  if (!lc1 && !lc2) 
   return lc_none;
 
// choose the first start
  if (lc1 && lc2)
   if (lc1 < lc2)
    lc2 = nullptr;
   else
    lc1 = nullptr;
 
// single line 
  if (lc1) 
   return (lc1 == s) ? lc_full : lc_part;
 
// multiline
  insideFlag = true;
  len -= (lc2 - s) + 2;
  s = lc2 + 2;     // advance to next
 }
 return insideFlag ? lc_full : lc_none;  // mistake, FIXME
}
Писал здесь, возможны ошибки. В общем, находите самую простую веточку и обрубаете ее, чтобы к ней не возвращаться. Пока все не будет вырублено

А вообще "концептуально" (не побоюсь этого слова) вопрос интересный. Да, очень заметно что код структурирован плохо, везде налипают проверки. Если где-то заклинит (или изменятся требования) - разобраться нереально. Да и вообще лягнуть начинающего - святое дело Но .. что делать? Как "лучше структурировать"? Привлечь крутое std:: вместо древнего char * - по-моему это мало что изменит. Хотя версия с std::string_view интересна
1
Покинул чат.
1133 / 728 / 195
Регистрация: 30.03.2021
Сообщений: 2,379
04.11.2025, 18:57
по-моему std::regex мог бы облегчить страдания
0
фрилансер
 Аватар для Алексей1153
6510 / 5770 / 1135
Регистрация: 11.10.2019
Сообщений: 15,413
04.11.2025, 19:18
sdf45, он медленный
0
Покинул чат.
1133 / 728 / 195
Регистрация: 30.03.2021
Сообщений: 2,379
04.11.2025, 20:05
Цитата Сообщение от Алексей1153 Посмотреть сообщение
sdf45, он медленный
Алексей1153, тогда я хз
0
Нарушитель
Эксперт функциональных языков программированияЭксперт С++
6700 / 3113 / 1064
Регистрация: 01.06.2021
Сообщений: 12,024
04.11.2025, 22:00
Цитата Сообщение от Алексей1153 Посмотреть сообщение
он медленный
а ты сравнивал? Просто этот слух идет со времен царя Гороха, когда оптимизаторы компилятора были отстойными. Может сейчас уже не такой медленный? Тем более, где гарантия, что костыль будет быстрым? Наверное, стоит проверить...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
04.11.2025, 22:00

Корректное завершение работы консольного приложения
Есть консольное приложение на Qt, которое запускает несколько потоков. Фактически в main я создаю...

Корректное освобождение памяти при принудительном завершении потока TThread
У меня в отдельном потоке выполняются некоторые вычисления. В процессе выполнения этой функции...

Потоки и их корректное завершение
Доброго времени суток! Необходима Ваша помочь. Есть поток, организованный так: void...

Корректное завершение
Когда закрываю окно QGraphicsView`а, процесс остается еще запущен и пишет еще что возникла ошибка....

Корректное завершение QCoreApplication
Добрый день! OC: Windows 7 Professional Qt: 5.7.0 Есть приложение QCoreApplication: int...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
Генератор паролей (вариант №2)
Maks 30.10.2026
Обновленная версия ранее созданной обработки. Добавлены следующие реквизиты типа Булево: - Буквы; - Цифры; - Символы. Изменена логика команды "Сгенерировать" и процедуры "ПриОткрытии":. . .
Генератор паролей (вариант №1)
Maks 29.10.2026
Реализация из решения ниже выполнена исключительно по моей инициативе, дабы облегчить себе работу в создании паролей для администрируемых мною сервисов и пользователей. Самым главным критерием для. . .
Установка ChatGPT (Codex) на Windows без использования Microsoft Store
Fabien159 28.10.2026
Здравствуйте всем читающим! Опишу процесс установки ChatGPT (Codex) на Windows, если по каким-то причинам у вас не получается устанавить его через Microsoft Store. И так: 1. Скачиваем с. . .
Программное добавление префикса в нумерацию документов
Maks 27.10.2026
Реализация из решения ниже выполнена в самописной конфигурации на БСП (помощь начинающему коллеге). Задача: Программно добавить префикс в нумерацию документов. Решение: В модуле объекта. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru