struct CheckResult check(char *path, char *buf) {
FILE *f = fopen(path, "r");
size_t len = fread(buf, 1, BUF_SIZE - 1, f);
fclose(f);
// не забыть про нулл-терминаторы в строках, это же Си, блин.
buf[len] = '\0';
// TODO(Robin): поискать ошибки
return result;
}
Во-первых использование мусорного libc. Работа с файлами и прочие потуги libc - это устаревшее говно. Это попытки реализовать абстракции на сишке, но сишка ненужна для абстракций. К тому же - абстракции эти зачастую - говно.Я уже более-менее подробно разбирал потуги. Лучше, я разберу его финальный вариант.
int main() {
char buf[BUF_SIZE];
struct CheckResult bad_results[MAX_RESULTS];
int num_results = 0;
char *paths[] = { "sample2.txt", "sample.txt", NULL };
for (int i = 0; paths[i] != NULL; i++) {
char *path = paths[i];
struct CheckResult result = check(path, buf);
bad_results[num_results++] = result;
}
for (int i = 0; i < num_results; i++) {
report(bad_results[i]);
}
}
Что пыталось родить это отребье - я не понимаю. Это дошколёнок - это даже не бездарный стундент. Но ладно.struct Mistake {
char *message;
// указывает на ошибку
char *location;
}
Любой текст, любая динамика - это говно. Хоть сишка и динамический язык, но это не скриптуха.Любой адекватный челове крешит это enum-флаго. В данном случае флаг один и он всегда есть - он вообще нунежен.
enum mistake_type {comma_error, /*что угодно */};
Так же спокойно пишется строковое представление об ошибке. Так должно происходить всегда. Особенно когда дело доходит до сериализации.Далее, отребье так же впиндюрило location, хотя это не location - это огрызок контеста в 12 байт(символов). Здесь очевидно, что огрызок окнтекста можно хранить сразу в структере, а так же там можно хранить любой контекст. Реализуется это так же просто - через char location[]; и записью после структуры.
Адресуется всё это дело списком, через size до location, где location + size - етсь следующий объект. Это позволяет экономить память, но треяется ro, что почти всегда плохо. Хотя маллок на каждую строку - это говно куда более худшее.
На самом деле нормальное размещение в памяти позволяет использовать индексы вместо указателей и различие по потреблению памяти можно уменьшить. Именно в этом смысл сишки и её подхода. Именно поэтому всякая С++-дристня, тот же raii(особенно в том мусорном виде, в котором его украл говнораст из С++)- говно и не зерокост.
Но, самое важное. Это ломается раст. Подобные структуры вообще не влезают в ту примитивную модель.
Как работает раст. Это говно позволяет иметь одну ссылку на объект. Это всегда неюзабельно. Далее, уже нужно пыхтеть руками. Т.е. явно указывать алиасы через '-дристню, но. Она имеет проблему, причём проблему фундаментальную. Когда мы шарим данные - их нужно читать. Где и кто будет читать - неясно.
Поэтому говнораст решил опять все поиметь. Он говорит “если есть шаринг - чистить нельзя”. А почему нельзя? Очень просто - нельзя позвать очисту на rw-объекте. Таким образом, если мы все ссылки сделаем ro - данные очистится никак не смогут.
А что это значит? Это значит, что если мы возьмём ссылку на часть нашей памяти(массива), то память сразу же станет ro. А значит ничего туда записать нельзя. Пропаганда настолько сильно обработала и сектантов и обычных людей, что реально верят в то, что в этом говне есть какой-то борроу-чекер. На самом деле его нет. Эта херня реализуется любым идиотом - подобная организация сводит на нет сложность борроу-чекера.
И я уже говорил, что тот же Wlifitime сваянный на коленке как PoC - на порядок сложнее раст-говна. Всё что вам нужно реализовать - это отслеживание времени жизни объектов. И это там реализовано - это реализовано уже на уровне семантики С++. Далее вам просто нужно заставить раба писать руками писать биндинг.
А далее, когда раб уже написал все связи между объектами за вас - вам нужно попросту отравить все ссылки(сделать их ro). Так же, нужно понимать, что на уровне говнораста нету объектов как они есть в C++. Там есть только ссылочные типы. Это говно обладает самантикой недоязычка с GC. Ведь вам может показаться, что разделение объект(сторедж)/ссылка может вызвать сложность. Нет - этого там нет.
И когда вам любая шлюха будет показывать кейс вида:
struct foobar_t {
void * ptr;
};
void foobar(void * ptr) {
struct foobar_t fb;
fb.ptr = ptr;
}
Знайте - шлюха вам обманывает. В этом говне нельзя написать так. Вам нужно руками связать fb.ptr и ptr. Т.е. никакой борроу-чекер тут ничего не даелает. Делают всё культяпки бездарные сектантов.Но вернёмся к задачи дерьма
typedef struct {//нам нужно создать структуру с нашей ошибкой.
// Здесь должна быть ссылка на message, но она ненужна.
// Если будет нужна - здесь будет enum, о чём я говорил выше.
char ctx[16];//нужно вставить сюда кусок контекста. Я возьму нормальное число, а не число дерьма
} bad_result_t;
Но для начала - посмотрим как должна выглядеть базовая функцияvoid checkv0(const char * path) {
int fd = open(path, O_RDONLY);
size_t size = file_size(fd);
void * data = mmap(NULL, size + 4096, PROT_READ, MAP_PRIVATE|MAP_POPULATE, fd, 0);
typeof(const char *) it = data, end = it + size;
while((it = strchrnul(it, ',')) < end)
fprintf(stderr, "ошибка дерьма: '%.12s'\n", it++);
munmap(data, size);
close(fd);
}
Всё остальное, что насрало это отребье - мусор. К тому же, raii есть и в си. Правда, всё это в рамках си автоматизируется другими средствами.По поводу ошибок. Никакой проверки ошибок в этом говне нет. Это отребье вас всегда обманывает. Если случится ошибка выделения памяти - это говно тут же сломается. Потому как нормальная работа с динамическими объектами без исключений существовать не может.
это говно(?), которое впаривает шлюха - это очередный мусорный ворованный синтаксический мусор. Это не обработка ошибок. Это просто мусор вида if(op() == error) return error; Если вам такой нужен - вы можете его засунуть в макрос.
Почему это не обработка ошибок? Обработка ошибок подразумевает их идентификацию. Здесь же, в этом говне, идентификация ошибок невозможна. Если нужна идентифкиация ошибок - нужно везде и всюду засирать сигнатуру + все ошибки должны иметь один тип. Что, очевидно, полная чушь в контексте нормальной типизации. Если же нам хватит одного типа - возвращай любой error_t в сишке.
Компилятор Rust. Не собирает программу. С багом, который уже был в программе на Си! Но Си его съел и выдавал в рантайме бред, а Rust считает ошибкой компиляции!!
О боже, я только сейчас это увидел. Это вся суть раст-пропаганды. Проблема в том, что это говно не позволяет шарить данные. И тут шлюха специально сделал ошибку на шаринге что-бы потом сделать подмену понятий. Т.е. хомячки думают, что говнораст здесь увидел ошибку при использовании шаринга. Нет - он увидел просто шаринг. И там могло не быть ошибки.
Далее эта мразь начала прятать код и съезжать с темы, кукарекая про какое-то там форматирование. Что пыталась добиться этим мразь. Получилось так, что её говно несмотря на все ухищрения, манипуляции оказалось страшнее его сишного дерьма. И что-то так сильно не палиться - шлюха начала менять условия. Т.е. “ну говна больше, но мы же сделали больше” и хомячок уже “думает”, что да. Оно страшное не потому, что говнораст дерьмо - нет. Просто больше функционала.
Второе я уже описал выше. Надо отвлечуть хомячка от проблемы выше. Клоун должен запомнить и побежать дальше. Запомнить враньё.
Примерный набросок того, как должно это выглядеть:
void check(const char * path, bad_result_t ** out) {
int fd = open(path, O_RDONLY);
size_t size = file_size(fd);
void * data = mmap(NULL, size + 4096, PROT_READ, MAP_PRIVATE|MAP_POPULATE, fd, 0);
typeof(const char *) it = data, end = it + size;
while((it = strchrnul(it, ',')) < end) {
// *(*out) = (bad_result_t){}; если мы хотим инициалихзации дефолтной
memcpy((*out)->ctx, it++, 12);
assert(strlen((*out)->ctx) == 12);
++(*out);
}
munmap(data, size);
close(fd);
}
int main() {
size_t total_tam = 1024ul * 1024 * 1024 * 10;
bad_result_t * data = mmap(NULL, total_tam, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
typeof(data) it = data, end = data;
check("./test.file", &end);
while(it < end) fprintf(stderr, "ошибка дерьма: '%s'\n", (it++)->ctx);
}
О, Царь, а расскажи про RAII в С++. Плюсы и минусы на твой взгляд, а то его сейчас везде как серебрянную пулю пихают, мол решит все ваши проблемы с ресурсами и памятью.
ОтветитьУдалитьБыло бы здорово почитать твое видение того, что брать посонам в дорогу из модернС++ если они решили начать новый проект не отягощённый грузом легаси. Тоесть очевидно, что что-то из того что есть сейчас в С++17/20 было актуально во времена С++99, а сейчас нафиг не нужно.
ОтветитьУдалить+1
УдалитьЕще вот эти фишки типа hana и оператора-трубы который он юзает в ч. 3.
краш курс для пацанов с разбором, серия мастер класса