steinkrauz

> Recent Entries
> Archive
> Friends
> User Info
> previous 20 entries

December 22nd, 2023


05:38 pm - Си -- говно, а MSVC -- дважды.
Как вы думаете, на что я сегодня убил полдня? Правильно, на отладку сишного кода. Полдня это потому что код сидит внутри библиотеки, которая дёргается в рантайм-контексте. Поэтому никаких тестов, скомпилили библиотечку, засунули в систему, подняли клиента, дёрнули процесс, система упала, посмотрели логи, вернулись к началу.

ну ладно, я человек упорот упорный, докопался. Так как в Си, как известно, строк нет, у меня был статический массивчик, куда клалось имя текущего верхнего элемента с тем, что если в кишках его найдётся ошибка, добавить это имя в лог. Потыкав пальцем в небо, я дал этому массиву размер в 128 байт, потому как для большинства имён это было с хорошим запасом. Но кому-то понадобилось назвать элемент «Установка прокладкоустойчивой канализационной арматуры с автоматическим фекальным запором "Сфинктер-ВЖ-ЕБ" №2». И, бинго, оно оказалось 129 символов, почему на моменте копирования из контейнера в переменную всё и рушилось.

Казалось бы, причём тут MSVC, когда сам рак? Чукча, конечно, тупой, но соломку подстелил: копировалось оно безопасной функцией strcpy_s. В MSDN пикселями по экрану четко написано: возвращаем код ошибки и ставим dest[0]=0, если dest слишком маленький. То есть по идее в случае слишком длинного имени я максимум получаю неполное сообщение о проблеме в логе проверок, и то, если оно таки будет. Собственно почему так долго и искал: всё смотрел глубже по коду, а strcpy_s она ж безопасная, там все проверки есть. Авотхуй, при копировании большего буфера в меньший трапнулась, как таиландский шимейл.

(7 comments | Leave a comment)

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. Учитывая, что последние несколько дней я в основном ленился, получается, что на эту фитюльку ушёл ровно месяц. Йопаный стыд.

(2 comments | Leave a comment)

April 20th, 2022


11:09 pm - c# command line parser
Писал, значится я себе соксопрокси, и чтобы не заморачиваться с файлом конфигурации, решил все настройки делать через командную строку. Тупым перебором с кучей сравнений или хитрым свитчем делать это было не интересно, да и бинарный сериалайзер я только что написал... В общем, эта хрень работает через рефлексию. Зато практически никакого запутанного кода, и минимум писанины для конечного пользователя.

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


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

Смотреть тут

https://github.com/steinkrauz/StkCli

(30 comments | Leave a comment)

April 5th, 2022


11:35 pm - stkHTTor - Dogfooding
DISCLAIMER. Во всём виновата эта остроухая сволочь из Хьюстона, научившая плохому.

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

В основном оно уже работает:


Осталось только прикрутить ключи командной строки, чтобы можно было указавать порты, и в общем-то можно будет публиковать. Требует оно .NET 5, так что по идее ещё и кросплатформенно, но это надо будет отдельно проверить.

Fun fact: made with pure editor, 100% IDE free.
proof )

(3 comments | Leave a comment)

February 4th, 2022


08:59 pm - Запретите уже Си
Потому что у меня лапки и я в Си не могу.

Полдня исправлял странный баг, при котором документ с одной привязкой отображался в системе нормально, а с двумя и более — рушил всё намертво. А оказалось совершенно элементарно, я написал
*docs[i++] = sp_tags[j];


вместо того, чтобы
(*docs)[i++] = sp_tags[j];


Ну да, забыл про приоритеты.

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

(15 comments | Leave a comment)

February 2nd, 2022


10:05 pm - Статистика TrueConf
Накидал на днях анализатор логов TrueConf. Чтобы, значится, можно было сказать, сколько конференций было за день, кто участвовал, сколько вся эта мутотень длилась.

https://github.com/steinkrauz/trcanal

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

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

Тьфу.

(6 comments | Leave a comment)

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



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

(15 comments | Leave a comment)

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);


то всё заработает как полагается.

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

(14 comments | Leave a comment)

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!

(20 comments | Leave a comment)

April 5th, 2018


10:47 pm - Пых-пых
И чего все так PHP ругают? Пришлось тут на днях переписывать старую веб-мордочку в более приличный вид, так на удивление без боли и отвращения пошло. Подгорало, конечно, когда без явно выраженного квалификатора переменная просто считалась новой локальной и теряла данные, что порождало необъяснимы глюки, но это мелочи.

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

(3 comments | Leave a comment)

February 16th, 2018


09:22 pm - String Builder
Дело было вечером, делать было нечего — в общем на всякий случай переписал свой string builder на чистом Си.

Код всё там же:
https://bitbucket.org/steinkrauz/string_builder

(Leave a comment)

December 19th, 2017


11:47 pm - Марафон бесполезного софта
В кои-то веки написал что-то общеупотребительное, а не очередной хак над говноAPI или тупой вызов функционала.

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

string_buider

Простейший класс, который аппендит кучу строк в свой буфер, а потом отдаёт это одной нормальной строкой.
Это даже не библиотека, просто кидаете файлы в проект и наслаждаетесь.

Если случится странное, и кому-то захочется посмотреть на код, то это здесь:
https://bitbucket.org/steinkrauz/string_builder

(4 comments | Leave a comment)

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

(5 comments | Leave a comment)

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();

(3 comments | Leave a comment)

October 29th, 2014


12:09 am - Нытья псто
Постиг новые бездны отчаяния — написание передачи данных из приблуды через уёб-фронтенд. Сначала эти несчастные данные проваливаются в клиентскую библиотеку, потом их пережёвывает веб-сервер, затем глотает интерпретатор, наконец переваривает скрипт и, ВНЕЗАПНО, на выходе получается хуй. А получить какой-то сигнал из кишок этой говноцепочки та ещё задача, сравнимая по трудоёмкости с исходной. Вот блядь бегаешь кругами по потолку, пытаясь понять, в каком месте всё портится, потом падаешь на пол, стукаешься башкой и видишь, что в Content-Type опечатка. Правишь её -- и заебись, всё работает. Где сломалось, почему сломалось -- хрен узнаешь, потому как никто такие тонкости нихрена не описывает.

(7 comments | Leave a comment)

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, конечно, удобно, но жирно, медленно и уродливо. Кто что может предложить по поводу формата обмена данными?

(13 comments | Leave a comment)

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;
}
Господа программисты! Кто может объяснить тупому мне сакральный смысл этого метода? (Про машинное эпсилон знаю, но тут мысль явно пошла глубже)

(4 comments | Leave a comment)

May 15th, 2014


09:52 am - На почитать
http://javarevisited.blogspot.ca/2014/05/10-articles-every-programmer-must-read.html

(3 comments | Leave a comment)

May 12th, 2014


12:13 pm - Сру на степанова
Вот почему блеать erase в контейнере должен обязательно сдвигать итератор вперёд, а не оставлять его инвалидным, а не рушить принцпип одна функция -- одно действие?

UPD: Возможно, что в С++11 это поправили, создав относительно нормальный foreach, но из-за совместимости есть только С++03. А в легкотрёпе это вообще было, чего бы сразу не слямзить.

(Leave a comment)

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

(12 comments | Leave a comment)

> previous 20 entries
> Go to Top
LJ.Rossia.org