|
December 22nd, 2023
05:38 pm - Си -- говно, а MSVC -- дважды. Как вы думаете, на что я сегодня убил полдня? Правильно, на отладку сишного кода. Полдня это потому что код сидит внутри библиотеки, которая дёргается в рантайм-контексте. Поэтому никаких тестов, скомпилили библиотечку, засунули в систему, подняли клиента, дёрнули процесс, система упала, посмотрели логи, вернулись к началу.
ну ладно, я человек упорот упорный, докопался. Так как в Си, как известно, строк нет, у меня был статический массивчик, куда клалось имя текущего верхнего элемента с тем, что если в кишках его найдётся ошибка, добавить это имя в лог. Потыкав пальцем в небо, я дал этому массиву размер в 128 байт, потому как для большинства имён это было с хорошим запасом. Но кому-то понадобилось назвать элемент «Установка прокладкоустойчивой канализационной арматуры с автоматическим фекальным запором "Сфинктер-ВЖ-ЕБ" №2». И, бинго, оно оказалось 129 символов, почему на моменте копирования из контейнера в переменную всё и рушилось.
Казалось бы, причём тут MSVC, когда сам рак? Чукча, конечно, тупой, но соломку подстелил: копировалось оно безопасной функцией strcpy_s. В MSDN пикселями по экрану четко написано: возвращаем код ошибки и ставим dest[0]=0, если dest слишком маленький. То есть по идее в случае слишком длинного имени я максимум получаю неполное сообщение о проблеме в логе проверок, и то, если оно таки будет. Собственно почему так долго и искал: всё смотрел глубже по коду, а strcpy_s она ж безопасная, там все проверки есть. Авотхуй, при копировании большего буфера в меньший трапнулась, как таиландский шимейл.
|
April 29th, 2022
11:00 pm - stkHTTor: Release Мы строили, строили и наконец построили! Урря!
Как я уже писал ранее, это совершенно тупая утиль, работающая прослойкой между программой, не умеющей в SOCKS-прокси, и Tor'ом. Заодно показывает хуй урядовому лайну, которое хотело лишить меня эльфийских веществ.
Кроме того, что криво-косо изображает из себя прокси, оно умеет следующее:
- Запускаться как консольное приложение и писать свой pid в файл, чтобы можно было легко убить
- Брать адрес, на котором слушать запросы, из переменной http_proxy
- Не делает больше ничего лишнего
- Не требует конфигурационных файлов
Лежит как всегда на шитхабе: https://github.com/steinkrauz/stkhttor
P.S. Дата создания проекта: 26 марта 2022 г., 22:45:23. Учитывая, что последние несколько дней я в основном ленился, получается, что на эту фитюльку ушёл ровно месяц. Йопаный стыд.
|
April 20th, 2022
11:09 pm - c# command line parser Писал, значится я себе соксопрокси, и чтобы не заморачиваться с файлом конфигурации, решил все настройки делать через командную строку. Тупым перебором с кучей сравнений или хитрым свитчем делать это было не интересно, да и бинарный сериалайзер я только что написал... В общем, эта хрень работает через рефлексию. Зато практически никакого запутанного кода, и минимум писанины для конечного пользователя.
А потому, поддавшись тлетворному влиянию эльфийских товарищей, всё это дело я оформил в отдельную библиотеку, точнее просто файлик с исходниками, которой можно тупо добавить в свой проект и использовать. Что оно умеет:
- короткую и длинную форму для параметра
- целые, дробные и строковые значения для параметров
- обязательность параметра
- параметр-флаг
- автоматическая генерация справки
В принципе, базовые потребности закрывает, для чего-то более извращённого лучше использовать более сложные вещи.
Смотреть тут
https://github.com/steinkrauz/StkCli
|
April 5th, 2022
11:35 pm - stkHTTor - Dogfooding DISCLAIMER. Во всём виновата эта остроухая сволочь из Хьюстона, научившая плохому.
В общем, мне не понравились существующие тулзы, и я написал свою, которая тупо изображает из себя HTTP-прокси, а на самом деле отправляет запросы через Tor (который в свою очередь изображает из себя SOCKS-прокси, а этот вариант умеют использовать не только лишь все утилиты, мало кто может).
В основном оно уже работает:
Осталось только прикрутить ключи командной строки, чтобы можно было указавать порты, и в общем-то можно будет публиковать. Требует оно .NET 5, так что по идее ещё и кросплатформенно, но это надо будет отдельно проверить.
Fun fact: made with pure editor, 100% IDE free. ( proof )
|
February 4th, 2022
08:59 pm - Запретите уже Си Потому что у меня лапки и я в Си не могу.
Полдня исправлял странный баг, при котором документ с одной привязкой отображался в системе нормально, а с двумя и более — рушил всё намертво. А оказалось совершенно элементарно, я написал
вместо того, чтобы
(*docs)[i++] = sp_tags[j];
Ну да, забыл про приоритеты.
В общем, заберите нах это пакость, где ссылки на ссылки на куски памяти передают, и дайте с нормальными контейнерами подеградировать.
|
February 2nd, 2022
10:05 pm - Статистика TrueConf Накидал на днях анализатор логов TrueConf. Чтобы, значится, можно было сказать, сколько конференций было за день, кто участвовал, сколько вся эта мутотень длилась.
https://github.com/steinkrauz/trcanal
Продукт выдаёт в консоль и в базу данных, чтобы потом можно было генеральские графики строить.
Вот так вот и деградируешь потихоньку. Потому что сначала спарсить лог конференциий, потом спарсить лог звонков, затем спарсить лог веб-сервера портала (потому что, блядь, т.н. админы шарепойнта не способны из него достать статистику показа страничек, ага). А на что-то хотя бы немного сложное и познавательное времени в результате не остаётся.
Тьфу.
|
March 29th, 2021
09:53 am - Кресты -- говно Рассмотрим сферический пример в вакууме: две проце дуры, каждая из которых итерирует последовательный коньтейнер и добавляет туда элементы.
#include <iostream>
#include <vector>
#include <list>
using namespace std;
void fart1()
{
vector<int> c;
c.push_back(1);
for(auto a:c) {
c.push_back(a++);
if (c.size()>10) break;
}
cout<<"Count:"<<c.size()<<"\n";
}
void fart2()
{
list<int> c;
c.push_back(1);
for(auto a:c) {
c.push_back(a++);
if (c.size()>10) break;
}
cout<<"Count:"<<c.size()<<"\n";
}
int main()
{
fart1();
fart2();
return 0;
}
Казалось бы, в языке здорового человека никаких различий быть не может. Но плюсы считают по-другому:
[stk@archtest Source]$ ./cppshit
Count:2
Count:11
ибо у этих пидоров реализация течёт сквозь абстракцию даже в стандартной библиотеке, причём на официальном, мать их, уровне.
|
July 30th, 2020
12:14 am - Нюансы сишечки Я в принципе сишечку довольно-таки люблю, и даже к плюсам отношусь тепло. Но иногда как вляпаешься...
Если написать вот так:
char *str = "1111-2222-333-444/001";
char *pC = strstr(str, "/");
if (pC!=NULL) *pC = '\0';
puts(str);
то получим segmentation fault (core dumped).
А вот если мы напишем вот так
char str[] = "1111-2222-333-444/001";
char *pC = strstr(str, "/");
if (pC!=NULL) *pC = '\0';
puts(str);
то всё заработает как полагается.
Не, полминуты чесания тыковки, и причины становятся совершенно очевидными, а тем, кто сразу видит выжимку из кода так и ещё быстрее всё понятно станет. Но изначально это проявилось при тестировании уже рабочего куска кода, который внезападно вдруг начал крашиться. Омерзительное ощущение.
|
December 10th, 2019
08:24 pm - Пора на свалку, на свалку пора Знаете, что забавно в этом примере? Нет, не то, что там элементарная ошибка. А то, что компилятор из этого вполне себе создаст исполняемый файл. Варнинг, конечно, будет, и для этого примера отлично виден. Только вот когда проект большой, поймать новое сообщение в летящей простыне вывода практически невозможно.
#include <iostream>
#include <algorithm>
#include <vector>
std::vector<int> make(size_t size)
{
std::vector<int> res;
for (size_t i; i<size; i++)
res.push_back(size-i);
std::sort(res.begin(), res.end());
}
int main(int argc, char *argv[])
{
std::vector<int> data = make(5);
for (int i:data)
std::cout<<i<<" ";
std::cout<<"\n";
return 0;
}
Угу, это по результатам сегодняшних приключений, когда час бился головой об стенку, не понимая, с какого перепуга обращение к std::string даёт ошибку генерала Фолта.
CPP PEDIBUS DESTRUE!
|
April 5th, 2018
10:47 pm - Пых-пых И чего все так PHP ругают? Пришлось тут на днях переписывать старую веб-мордочку в более приличный вид, так на удивление без боли и отвращения пошло. Подгорало, конечно, когда без явно выраженного квалификатора переменная просто считалась новой локальной и теряла данные, что порождало необъяснимы глюки, но это мелочи.
С другой стороны, мне достался уже PHP5, а что там в ранних версиях было, того не ведаю. Может действительно сплошной мрак и псоглавцы бегают.
|
February 16th, 2018
December 19th, 2017
11:47 pm - Марафон бесполезного софта В кои-то веки написал что-то общеупотребительное, а не очередной хак над говноAPI или тупой вызов функционала.
В общем, для таких же идиотов, как я, которым приходится работать с сишными строками, а тащить STL или ещё какие жирные библиотеки неохота. Или же для тех, у кого употребление стандартных аллокаторов может вызывать несварение в программе:
string_buider
Простейший класс, который аппендит кучу строк в свой буфер, а потом отдаёт это одной нормальной строкой. Это даже не библиотека, просто кидаете файлы в проект и наслаждаетесь.
Если случится странное, и кому-то захочется посмотреть на код, то это здесь: https://bitbucket.org/steinkrauz/string_builder
|
April 21st, 2017
10:33 pm - Фрагментация памяти Навеяло дискуссией в бложике у Кетмара. Дескать, что будет, если мы начнём память дёргать туда-сюда тупо в лоб, не задумываясь о последствиях? Отсюда родилась тупенькая программа, которая это дело исследует. Алгоритм совершенно дубовый: читаем файл в массив строк, дальше треть этого массива рандомно заменяем рандомно сгенерированными строками, и повторяем это тыщщу раз, с новыми строками для каждого раза, естественно. А в процессе замеряем, сколько времени потребовалось в каждый подход потратить на выделение памяти.
[stk@testarch memfrag]$ ./memfrag -m c test.txt
Char test selected
Total lines: 531
Max string length: 205
Allocation in load: 104ms
VM: 4256; RSS: 1268
Replace table has 177 entries
First ten allocations mean time: 35ms
Last ten allocations mean time: 39ms
Allocation time changes by 111%
VM: 9792.00; RSS: 8344.00
На маленьком файле вроде всё в порядке, ну память подросла, так и строки размером побольше могли вставиться, а по времени так вообще в пределах флюктуаций. Теперь берём файл побольше
[stk@testarch memfrag]$ ./memfrag -m c test2.txt
Char test selected
Total lines: 3181
Max string length: 205
Allocation in load: 639ms
VM: 4520; RSS: 2856
Replace table has 1060 entries
First ten allocations mean time: 225ms
Last ten allocations mean time: 421ms
Allocation time changes by 186%
VM: 46360.00; RSS: 44920.00
И тут так внезапно объём памяти вырастает на порядок, а время на её выделение почти в два раза. У-у-у-пс. Это чистые плюсы без излишеств, только выделение памяти под массивы. А теперь попробуем то же самое, но с контейнером и строками из STL:
[stk@testarch memfrag]$ ./memfrag -m s test2.txt
String test selected
Total lines: 3181
Max string length: 205
Allocation in load: 799ms
VM: 4572; RSS: 2988
Replace table has 1060 entries
First ten allocations mean time: 254ms
Last ten allocations mean time: 160ms
Allocation time changes by 62%
VM: 6156.00; RSS: 4820.00
А у них внезапно и с памятью, и со скоростью всё более, чем нормально. Но как говорится, и на старуху найдётся проруха: если вместо 1000 пустить 1300 итераций, что-то в аллокаторе всё-таки ломается.
First ten allocations mean time: 217ms
Last ten allocations mean time: 1341ms
Allocation time changes by 617%
VM: 6156.00; RSS: 4728.00
Если кто хочет сам поиграться, прога лежит на Bitbucket: https://bitbucket.org/steinkrauz/memfrag
|
February 19th, 2015
10:20 am - Pacepalm 40 аналитиков, 15 программистов, промышленная организация разработки ПО, ТЗ по ГОСТу...
Результат настолько прекрасен, что не нуждается в комментариях.
public static int getTypeOfDB(DMSession dmSession)
{
int type = 3;
try
{
if (dmSession.getCurrentSite().toString().startsWith("stidb1")) {
type = 0;
} else if ((getDB(dmSession) == 6) || (getDB(dmSession) == 7)) {
type = 2;
} else if ((getDB(dmSession) == 11) || (getDB(dmSession) == 12)) {
type = 3;
} else if (((getDB(dmSession) == 4) || (getDB(dmSession) == 5)) && (getDB(dmSession) != 13) && (getDB(dmSession) != 14)) {
type = 3;
} else if (getDB(dmSession) == 9) {
type = 4;
} else if (getDB(dmSession) == 8) {
type = 1;
} else if ((getDB(dmSession) == 0) || (getDB(dmSession) == 1) ||
(getDB(dmSession) == 13) || (getDB(dmSession) == 14)) {
type = 5;
} else if ((getDB(dmSession) == 2) || (getDB(dmSession) == 3) ||
(getDB(dmSession) == 10) ||
(getDB(dmSession) == 0) || (getDB(dmSession) == 1)) {
type = 6;
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
public static int getDB(DMSession dmSession)
{
int type = -1;
try
{
dmSession.getCurrentSite().toString();
String value_list = dmSession.getPreferenceService().getString(0, "KUPD_DB_type");
if ((list_t == null) || (list_t.size() == 0))
{
list_t.put("DB_PC21_ZAI_WORK", Integer.valueOf(0));
list_t.put("DB_PC21_ZAI_TEST", Integer.valueOf(1));
list_t.put("DB_PC21_OKB_WORK", Integer.valueOf(2));
list_t.put("DB_PC21_OKB_TEST", Integer.valueOf(3));
list_t.put("DB_BISON_ZAI_WORK", Integer.valueOf(4));
list_t.put("DB_BISON_ZAI_TEST", Integer.valueOf(5));
list_t.put("DB_STIDB_ZAI_WORK", Integer.valueOf(6));
list_t.put("DB_STIDB_ZAI_TEST", Integer.valueOf(7));
list_t.put("DB_ICARUS_ZAI_TEST", Integer.valueOf(8));
list_t.put("DB_ICARUS_ZAI_WORK", Integer.valueOf(9));
list_t.put("DB_BISON144OKB_WORK", Integer.valueOf(10));
list_t.put("DB_SU_ZAI_WORK", Integer.valueOf(11));
list_t.put("DB_SU_ZAI_TEST", Integer.valueOf(12));
list_t.put("DB_BISON144ZAI_WORK", Integer.valueOf(13));
list_t.put("DB_BISON144ZAI_TEST", Integer.valueOf(14));
}
if (list_t.toString().contains(value_list)) {
type = ((Integer)list_t.get(value_list)).intValue();
} else if (!list_t.toString().contains(value_list)) {
com.dmcenter.rac.util.MessageBox.post(Desktop.getActiveDesktop(), "Не найдено соответствующего типа для базы!", "Предупреждение", 2);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
return type;
}
return type;
}
static HashMap<String, Integer> list_t = new HashMap();
|
October 29th, 2014
12:09 am - Нытья псто Постиг новые бездны отчаяния — написание передачи данных из приблуды через уёб-фронтенд. Сначала эти несчастные данные проваливаются в клиентскую библиотеку, потом их пережёвывает веб-сервер, затем глотает интерпретатор, наконец переваривает скрипт и, ВНЕЗАПНО, на выходе получается хуй. А получить какой-то сигнал из кишок этой говноцепочки та ещё задача, сравнимая по трудоёмкости с исходной. Вот блядь бегаешь кругами по потолку, пытаясь понять, в каком месте всё портится, потом падаешь на пол, стукаешься башкой и видишь, что в Content-Type опечатка. Правишь её -- и заебись, всё работает. Где сломалось, почему сломалось -- хрен узнаешь, потому как никто такие тонкости нихрена не описывает.
|
September 24th, 2014
09:35 pm - Помощь зала Всплыла тут задача: обмениваться данными между программами. Причём программы пишутся на разных языках (C# и C/C++) и возможно будут работать на разных серверах. Подход в лоб: юзаем .NETовский XMLSerializer и гоняем что-то вроде такого:
<?xml version="1.0" encoding="UTF-8"?>
<Data xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Name>Пизда Ивановна</Name>
<Value>3.14159</Value>
<vectors>
<XZVector>
<x>1</x>
<y>0</y>
<z>0</z>
</XZVector>
<XZVector>
<x>0</x>
<y>1</y>
<z>0</z>
</XZVector>
<XZVector>
<x>0</x>
<y>1</y>
<z>0</z>
</XZVector>
</vectors>
</Data>
(вид упрощённый, но примерно так и будет: головная стуктура с атрибутами и несколькими коллекциями других структур. Дочерние структуры тоже имеют атрибуты и коллекции структур. Внучатые в основном просто с атрибутами).
Собственно, вопрос. XML, конечно, удобно, но жирно, медленно и уродливо. Кто что может предложить по поводу формата обмена данными?
|
September 12th, 2014
05:44 pm - Моск кончился
static bool diff(double a, double b) {
double d = Math.Abs(a - b);
double v = Math.Abs(a) + Math.Abs(b);
if (d < 0.001) return false;
if (v > 0) {
double z = d / v;
if (z > 0.002) return true;
}
return false;
}
Господа программисты! Кто может объяснить тупому мне сакральный смысл этого метода? (Про машинное эпсилон знаю, но тут мысль явно пошла глубже)
|
May 15th, 2014
May 12th, 2014
12:13 pm - Сру на степанова Вот почему блеать erase в контейнере должен обязательно сдвигать итератор вперёд, а не оставлять его инвалидным, а не рушить принцпип одна функция -- одно действие?
UPD: Возможно, что в С++11 это поправили, создав относительно нормальный foreach, но из-за совместимости есть только С++03. А в легкотрёпе это вообще было, чего бы сразу не слямзить.
|
April 28th, 2014
12:22 pm - Перлы продолжаются
Вызов:
long item_chk_time = ercSession.mysql.GetItemCheckTime(item_id);
long item_forced = ercSession.mysql.GetItemForced(item_id);
Реализация:
public long GetItemCheckTime(String part_id) {
return GetLong("SELECT part_time FROM items WHERE part_id=\"" + part_id + "\"");
}
public long GetItemForced(String part_id) {
return GetLong("SELECT part_forced FROM items WHERE part_id=\"" + part_id + "\"");
}
И да, как правильно догадался внимательный читатель, part_forced -- это флажок со значениями 0 и 1, имеющий в базе тип bigint(20).
Пердыдущий перл 1
Пердыдущий перл 2
|
|
|