+130
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
#include <stdlib.h>
struct no_matter
{
int some_field;
};
struct matter *do_stuff(void)
{
struct no_matter *m = calloc(1, sizeof *m);
return m;
}
int main(void)
{
struct no_matter *m = do_stuff();
free(m);
return 0;
}
Сегодня выполняю роль гумна. В сишке можно возвращать указатель на непонятно откуда взявшуюся необъявленную ранее структуру и код будет компиляться (ладно хоть пишет невнятные ворнинги, только благодаря им нашёл опечатку в одной букве в имени структуры в рабочем коде). Понятно, что все указатели одинаково числа, но всё равно как-то некрасиво. Хацкелисты негодуэ, даёшь монаду Ptr
http://ideone.com/3SABHW
Запостил:
roman-kashitsyn,
27 Ноября 2012
структура объявлена до первого использования, calloc честно выделяет память, free честно удаляет её
> struct no_matter *
calloc и free здесь не при чём, они просто отражают ситуацию, с которой я столкнулся.
Я знаю, почему это работает, мне просто не нравится, что оно должно компилиться (теперь только -Werror, только хардкор).
с первого раза и не углядишь даже
Вот и я о том же: ещё один отличный способ выстрелить себе в ногу.
как и использование необъявленных типов
я всегда буду обновлять тред перед отправкой комментария
я всегда буду обновлять тред перед отправкой комментария
я всегда буду обновлять тред перед отправкой комментария
я всегда буду обновлять тред перед отправкой комментария
> я всегда буду обновлять тред перед отправкой комментария
> я всегда буду обновлять тред перед отправкой комментария
> я всегда буду обновлять тред перед отправкой комментария
Каждый раз, когда не обновляешь - на 1 строчку больше дописываешь?
Fixed.
Просто можно указателю на одну структуру присвоить указатель на другую, и сишка это съест.
Видимо, Ритчи изобрёл Dynamic Typing задолго до того, как это стало мэйнстримом.
Это возможно далеко не всегда. Например, если размер структуры не известен клиентскому коду (а в моём случае это верно чуть чаще чем всегда: клиенты работают с загадочным struct something *, не зная, что внутри).
Экземпляры порождаются/уничтожаются с помощью allocate_something() / deallocate_something(), за правильный вызов отвечает клиент.
1) вызываем с параметром "длина моего буфера - 0", получаем "длина твоего буфера будет 25 см"
2) вызываем с "длина моего буфера - 25 см", получаем "окей, теперь смотри сам свой буфер"
Что-то мне подсказывает, что это чревато race-conditions (необходимая длина буфера может поменяться между вызовами). Да и аллокации в куче это избежать не особо помогает, разве что через alloca, чревытый последствиями.
если передать 0, вызов говорит error_more_data и говорит сколько (25 см)
вызываем с 25 см, вызов говорит error_more_data и говорит, что теперь надо 30 см
выделяем 40 см, вызов говорит "ок, записал 30 см"
но в целом это не очень хорошо, если длина может так меняться от двух последовательных вызовов
да и вообще - сишкопроблемы
Гораздо хуёвее, если функция "заполни мне буфер" не принимает размер буфера. Она просто заполняет его как есть. И такая дыра есть в некотрых контролах ВинАПИ. Но это похуй, потому что похакать интерфейс и так есть много куда более простых способов, чем попасть в тот момент, когда программ уже узнала размер буфера, но ещё не отправила запрос на копирование данных.
Или записывают в свой локальный буфер и возвращает указатель на него.
Это вообще эпик фейлы стандартной сишной библиотеки (gets, sprintf, localtime, etc. - это ещё один пример того, когда не надо повторять за разработчиками api).
Да и хакеров, в плохом смысле этого слова, тогда еще не было, а юзеры не вводили всякий хлам, поэтому gets и sprintf не вызывали ни у кого опасений...
Хорошее было время...
P.S. Еще доставляет имя функции creat(). Такое ощущение, что имена были ограничены пятью символами.
Некоторые линковщики не воспринимали больше шести.
Ken Thompson was once asked what he would do differently if he were redesigning the UNIX system. His reply: "I'd spell creat with an e."
Для небольшого числа относительно крупных объектов (например, том псевдо-файловой системы) использую кучу. Кстати, в моём случае в качестве struct no_matter была struct test_suite, гуляющая между функциями.
"Простите, но в треде появились новые сообщения, или кто-то что-то исправил."
Проблема в том, что сток показывает только первую версию комментария, которая до редактирования.
И потихоньку Говнокод превращается... превращается Говнокод... в говногитхаб.
Предыдущая версия комментария содержала ссылки на неавторитетные источники, поэтому была отклонена.
Звучит как Виктория Копро.