Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LwIP это потенциально опасное ПО или нет?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
AleksBak
Вот если я скажем делаю так (использую NetConn API):
Код
struct netconn *conn, *newconn;
err_t err, accept_err;

conn = netconn_new(NETCONN_TCP);

while (1)
{
    if (conn != NULL)
    {
        err = netconn_bind(conn, NULL, 7000);

        if (err == ERR_OK)
        {
            netconn_listen(conn);

            while (1)
            {
                accept_err = netconn_accept(conn, &newconn);

                /* Process the new connection. */
                if (accept_err == ERR_OK)
                {
                    ...
                }
            }
        }
        else
        {
            netconn_delete(conn);
        }
    }
}

Т.е. все "по мануалу" и вопросов тут нет. Но вот вопрос такой тут - в функцию netconn_accept(conn, &newconn); я передал указатель на newconn, а эта функция в ответ обновила его значением указателя на свою локальную переменную (как я понял). Т.е. др. словами говоря - она создала внутри у себя какую-то локальную переменную, а потом второй параметр этой самой функции обновила уже новым значением указателя на эту переменную. И как теперь это понимать - ведь та локальная переменная существует в куче, но может же в любой момент времени быть затерта. Т.е. все работает как бы "до поры - до времени" так получается? Пока не "затрется случайно" та локальная переменная другим чем-то в ОЗУ. Или я не так понял? Или тут эта переменная newconn как бы "неполноценно" используется и в ней только что-то одно временно берется и потому все безопасно работает? Спасибо.
AleksBak
Я после того как написал свой вопрос все переживал, что не привел код самой функции netconn_accept() из стека LwIP и думал "вот люди будут меня ругать, что не показал ее код тоже", а оказывается никто не ответил даже еще. Вот сама функция netconn_accept из стека (в ней я убрал все некомпилирующиеся куски кода из-за условной компиляции чтобы не загромождать лишним кодом, а также добавил комментарий в том месте где ожидается получение семафора - см. код):
Код
err_t netconn_accept(struct netconn *conn, struct netconn **new_conn)
{
    struct netconn *newconn;
    err_t err;


    LWIP_ERROR("netconn_accept: invalid pointer", (new_conn != NULL), return ERR_ARG;);
    *new_conn = NULL;
    LWIP_ERROR("netconn_accept: invalid conn", (conn != NULL), return ERR_ARG;);
    LWIP_ERROR("netconn_accept: invalid acceptmbox", sys_mbox_valid(&conn->acceptmbox), return ERR_ARG;);

    err = conn->last_err;
    if (ERR_IS_FATAL(err))
    {
        /* don't recv on fatal errors: this might block the application task
         waiting on acceptmbox forever! */
        return err;
    }

    /* т.к. 3-й параметр тут - timeout равен 0, то ждем бесконечно долго прихода message (так сделано в этой функции): */
    sys_arch_mbox_fetch(&conn->acceptmbox, (void **) &newconn, 0);

    /* Register event with callback */
    API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);

    if (newconn == NULL)
    {
        /* connection has been aborted */
        NETCONN_SET_SAFE_ERR(conn, ERR_ABRT);
        return ERR_ABRT;
    }

    *new_conn = newconn;
    /* don't set conn->last_err: it's only ERR_OK, anyway */
    return ERR_OK;
}

Обратите внимание на строку №<последняя строка - 3> тут - вот это и есть, то о чем я писал:
Код
    *new_conn = newconn;

т.е. приравнивается значение указателя из 2-го параметра значению указателя на локальную переменную структуры!

Т.е. вопрос такой в итоге (извините, что сложно может написал до этого) - "Почему эта функция netconn_accept() из стека LwIP возвращает фактически указатель на свою локальную переменную?? Это правильно??" Спасибо.
_NB
Цитата(AleksBak @ Apr 7 2016, 20:22) *
Т.е. вопрос такой в итоге (извините, что сложно может написал до этого) - "Почему эта функция netconn_accept() из стека LwIP возвращает фактически указатель на свою локальную переменную?? Это правильно??" Спасибо.

Она возвращает значение этой локальной переменной, а не указатель на нее
AleksBak
Цитата(_NB @ Apr 7 2016, 22:55) *
Она возвращает значение этой локальной переменной, а не указатель на нее

Нет не так. В эту функцию передается указатель на указатель - переменная new_conn и вот такое объявление ее как параметра функции:
Код
struct netconn **new_conn

Внутри функции объявляется свой, локальный указатель на структуру newconn (может тут кроется ответ на загадку т.к. при его объявлении выделяется память из какой-то "особой" памяти самого стека LwIP? но это бред все-таки). Далее, под конец, мы видим, что:
Код
*new_conn = newconn;

т.е. все как писал - по переданному указателю на указателю пишется значение своего локального указателя. Тут даже и пояснять мне уже не нужно т.к. может запутываю в итоге и непонятен будет вопрос - все и так видно как на ладони.
aaarrr
Цитата(AleksBak @ Apr 8 2016, 06:22) *
...по переданному указателю на указателю пишется значение своего локального указателя.

Так в чем опасность? Сами же написали значение, не указатель.
AleksBak
Цитата(aaarrr @ Apr 8 2016, 10:23) *
Так в чем опасность? Сами же написали значение, не указатель.

Возвращается обратно значение указателя. А через это значение указателя далее в коде (в вызвавшей функции) идут обращения к той структуре (см. код). Т.е. где-то в куче она все еще есть пока что! Т.е. обращаемся к ней, а она находится в куче (или же в "бывшей" памяти стека) в это время. Вот так все и выходит. Теперь надеюсь понятно да? Если теперь опять какую-то (любую) функцию вызовем, то она легко может затереть значение той переменной в RAM, а мы по-прежнему будем думать, что то значение валидное внутри вызывающей основной функции. У меня еще есть объяснение, что вот с точки зрения применения ОС (NetConn API только для ОС написано) тут вроде ничего "страшного" нет. Вроде бы! У каждой задачи свой стек и т.д. И поэтому эти стеки задач существуют в раздельности и нерушимы. Но на самом деле - если, как только что написал, снова вызовем какую-то любую функцию то значение структуры все равно покоцается в этом "нерушимом" стеке. Или опять-таки я не прав и все не так? И вообще зачем они так это сделали по-дурацки (так выходит)? Зачем этот LwIP себе еще отдельные порции RAM "отгребает" при инициализации? И не малые причем! Это все отдельные и другие вопросы (их много вообще-то). Но пока хотя бы на этот вопрос в теме кто бы ответил.
des333
AleksBak:

Представьте, Вам нужно написать функцию, которая будет внутри использовать malloc для выделения памяти.

Но указатель на выделенную память нужно вернуть не через возвращаемое значение, а через один из аргументов функции.

Подумайте, как бы Вы написали такую функцию -- уверен, это поможет найти ответ на Ваш вопрос sm.gif
AleksBak
Цитата(des333 @ Apr 8 2016, 11:13) *
...
Представьте, Вам нужно написать функцию, которая будет внутри использовать malloc для выделения памяти.
...

malloc-ом я память выделяю и сразу же дальше использую внутри функции. А тут в одной функции выделена память, создана переменная в этой памяти и возвращается указатель на эту созданную переменную. А в вызвавшей функции мы продолжаем обращаться к той переменной несмотря на то, что она когда-то была простой локальной переменной в той функции, а не у нас и не здесь. Так теперь понятно? Это же разные вещи тут. Еще вот объяснение у меня есть - может в этом LwIP не настолько все просто сделано и этот указатель, который возвращается указывает на какую-то особую "LwIP"-овскую суперпамять внутри RAM? Но что-то по коду такого не видно тут такого абсолютно. Надо бы отладчиком посмотреть, что и как когда будет возможность.
des333
Цитата(AleksBak @ Apr 8 2016, 10:36) *
...Так теперь понятно?...

Мне точно понятно, что Вы прочитали не всё моё сообщение sm.gif

Цитата
Но указатель на выделенную память нужно вернуть не через возвращаемое значение, а через один из аргументов функции.

Т.е. цель -- написать функцию-обёртку для malloc, которая будет не просто использовать память, а возвращать её наружу (и именно через аргумент).

Всё-таки советую Вам написать такую функцию sm.gif
А уже потом, если вопросы всё-таки останутся, то обсудить их.
AleksBak
Цитата(des333 @ Apr 8 2016, 11:50) *
...написать функцию-обёртку для malloc, которая будет не просто использовать память, а возвращать её наружу (и именно через аргумент).
Всё-таки советую Вам написать такую функцию sm.gif....

Да я Вам сразу отвечу как бы все это было бы. Что тут размышлять как и чего. Выделил память, ничего бы с ней не делал дальше и тут же вернул бы на нее указатель. И Все. А тут - выделяется память, в ней создается переменная, что-то с ней делается, а потом возвращается указатель на ту переменную, а далее мы у себя опять обращаемся к этой переменной откуда-то в куче (в мусорке), а если еще какую-то функцию вызовем по дороге вдруг неожиданно, то ничего не останется от той переменной в мусорке, но будем все равно к ней обращаться т.к. так учат нас.

Еще добавлю - где-то даже кажется есть строгое указание в рекомендациях, что так делать категорически не рекомендуется. Вот только не помню где это и кто бы подсказал бы тут.
des333
Цитата(AleksBak @ Apr 8 2016, 11:12) *
Да я Вам сразу отвечу как бы все это было бы. Что тут размышлять как и чего.


Это Ваш выбор sm.gif

Вы просили помощи, я пытался Вам помочь sm.gif
AleksBak
Цитата(des333 @ Apr 8 2016, 12:13) *
Это Ваш выбор sm.gif

Вы просили помощи, я пытался Вам помочь sm.gif

Ну да - спасибо и на этом. Кстати тут вообще-то ничего не выделяется - в смысле это не какая-то ненужная обертка для функции mallocc как Вы пишите с самого начала, а я пытаюсь Вам отвечать согласно такой теории и в итоге не прав оказываюсь. Здесь просто: 1. создается локальная переменная; 2. что-то делается; 3. и возвращается потом указатель на эту локальную переменную. Вот так правильное описание, что тут происходит.
gosha-z
Я правильно понимаю, что newconn во втором сообщении обретает значение при вызове sys_arch_mbox_fetch? Если да - то что говорит дока на эту функцию по поводу способа выделения памяти для этой структуры и последующего ее освобождения?
AleksBak
Цитата(gosha-z @ Apr 8 2016, 12:39) *
Я правильно понимаю, что newconn во втором сообщении обретает значение при вызове sys_arch_mbox_fetch?...

Эта структура newconn вот такая - см. ее объявление ниже и на выходе из функции в ней должны появится готовые уже заполненные поля. А в вызвавшей, основной функции мы уже пользуемся этим "готовым" набором (см. коммент в 1-м куске кода: "Process the new connection."):
CODE
/** A netconn descriptor */
struct netconn
{
/** type of the netconn (TCP, UDP or RAW) */
enum netconn_type type;
/** current state of the netconn */
enum netconn_state state;
/** the lwIP internal protocol control block */
union
{
struct ip_pcb *ip;
struct tcp_pcb *tcp;
struct udp_pcb *udp;
struct raw_pcb *raw;
} pcb;
/** the last error this netconn had */
err_t last_err;
/** sem that is used to synchroneously execute functions in the core context */
sys_sem_t op_completed;
/** mbox where received packets are stored until they are fetched
by the netconn application thread (can grow quite big) Это QueueHandle_t. */
sys_mbox_t recvmbox;
#if LWIP_TCP
/** mbox where new connections are stored until processed by the application thread Это QueueHandle_t. */
sys_mbox_t acceptmbox;
#endif /* LWIP_TCP */
/** only used for socket layer */
#if LWIP_SOCKET
int socket;
#endif /* LWIP_SOCKET */
#if LWIP_SO_SNDTIMEO
/** timeout to wait for sending data (which means enqueueing data for sending in internal buffers) */
s32_t send_timeout;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVTIMEO
/** timeout to wait for new data to be received (or connections to arrive for listening netconns) */
int recv_timeout;
#endif /* LWIP_SO_RCVTIMEO */
#if LWIP_SO_RCVBUF
/** maximum amount of bytes queued in recvmbox not used for TCP: adjust TCP_WND instead! */
int recv_bufsize;
/** number of bytes currently in recvmbox to be received,
tested against recv_bufsize to limit bytes on recvmbox
for UDP and RAW, used for FIONREAD */
s16_t recv_avail;
#endif /* LWIP_SO_RCVBUF */
/** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */
u8_t flags;
#if LWIP_TCP
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
this temporarily stores how much is already sent. */
size_t write_offset;
/** TCP: when data passed to netconn_write doesn't fit into the send buffer,
this temporarily stores the message.
Also used during connect and close. */
struct api_msg_msg *current_msg;
#endif /* LWIP_TCP */
/** A callback function that is informed about events for this netconn */
netconn_callback callback;
};

Цитата(gosha-z @ Apr 8 2016, 12:39) *
...Если да - то что говорит дока на эту функцию по поводу способа выделения памяти для этой структуры и последующего ее освобождения?

Не знаю. Я новичок тут и поэтому спросил как оно работает и почему так сделано.
Сергей Борщ
QUOTE (AleksBak @ Apr 8 2016, 10:27) *
3. и возвращается потом указатель на эту локальную переменную.
Где? Я вижу, что в процессе "2. что-то делается" в эту локальную переменную заносится указатель на созданный в куче объект. Потом этот указатель записывается в то место, которое было указано входным параметром. Что до вас и пытался донести des333.
AleksBak
Цитата(Сергей Борщ @ Apr 8 2016, 12:58) *
...Потом этот указатель записывается в то место, которое было указано входным параметром...des333.

Ну да - все так. Но этот указатель теперь указывает на переменную в этой куче. И эта переменная-структура (ее объявление см. выше) теперь уже заполнена прямо в этой же функции netconn_accept уже должна быть (!). Если же нет и указатель на нее равен NULL, то произошел дисконнект. А в вызвавшей основной функции мы пользуемся готовыми данными из этой переменной (которая находится в куче и не забываем об этом) и получается, что не имеем права никакую др. лишнюю операцию произвести чтобы не дай бог (ПО ведь тут на божьем слове держится) затереть значение этой переменной в куче. Вот так я понял. Если нет, то конечно сыплю голову пеплом как говорится.
Сергей Борщ
QUOTE (AleksBak @ Apr 8 2016, 11:21) *
и получается, что не имеем права никакую др. лишнюю операцию произвести чтобы не дай бог (ПО ведь тут на божьем слове держится) затереть значение этой переменной в куче.
Вы, вероятно, неправильно понимаете термин "куча" (heap). Вам не зря про malloc писали. Если память выделена в куче - она зарезервирована и никто ее затереть не сможет, разве что только захочет намеренно испортить, но намеренно можно испортить совершенно любую переменную.
AleksBak
Еще пояснение: newconn - это указатель на область памяти, в которую будет скопирован элемент из очереди ОС - так оказалось когда дальше просмотрел. Мы, в netconn_accept(), динамически выделили под эту область памяти место в размере структуры типа netconn:
Код
struct netconn *newconn;

Правильно?? Столько выделяется ведь? В процессе работы ОС, в эту динамически выделенную область памяти скопируется элемент очереди когда наступит событие что мы тут ожидаем (сконнектится кто-то). А потом, на выходе функции, в этой динамической памяти мы работаем опять с переменной структуры в ней. А если в этот момент времени кто-то покоцает эту динамически выделенную память?
Сергей Борщ
QUOTE (AleksBak @ Apr 8 2016, 12:31) *
А если в этот момент времени кто-то покоцает эту динамически выделенную память?
А если кто-то покоцает стек? А если кто-то затрет все ОЗУ?
AleksBak
Цитата(Сергей Борщ @ Apr 8 2016, 14:18) *
Вы, вероятно, неправильно понимаете термин "куча" (heap). Вам не зря про malloc писали. Если память выделена в куче - она зарезервирована и никто ее затереть не сможет, разве что только захочет намеренно испортить, но намеренно можно испортить совершенно любую переменную.

Я думал, что куча это типа мусорки и временно в ней создаем переменную (держим над мусорным ведром пока что), что-то делаем, а на выходе из функции бросаем ее в мусорное ведро (а там внутри что-то типа шреддера стоит и перемалывает это наш мусор). И больше, после выхода из функции, не надо лазить в это мусорное ведро и копаться в нем в поисках еды нашей переменной. Вот так думал если по "колхозному" пояснить. laughing.gif
Сергей Борщ
QUOTE (AleksBak @ Apr 8 2016, 12:38) *
Я думал, что куча это типа мусорки и временно в ней создаем переменную
Я вам даже ссылку привел. А вот чтение информации из интернета вслух - 100 евро в час, увы.
AleksBak
Цитата(Сергей Борщ @ Apr 8 2016, 14:36) *
...А если кто-то затрет все ОЗУ?

biggrin.gif

Цитата(Сергей Борщ @ Apr 8 2016, 14:41) *
Я вам даже ссылку привел. А вот чтение информации из интернета вслух - 100 евро в час, увы.

Большое Вам спасибо за нужное направление. И отдельное спасибо в первую очередь des333! До меня дошло более-менее, но самое главное не это в итоге! А то что если это так, то где-то тут пропущен оператор free!!! А в примере его как раз и нету! "Ти-ти" как говорит мне сынишка (3 года, а на грузовик говорит - "говивик" и т.п.). А это значит... smile3046.gif
Сергей Борщ
QUOTE (AleksBak @ Apr 8 2016, 12:53) *
где-то тут пропущен оператор free!!! А в примере его как раз и нету!
Поищите в этом примере netconn_delete()
ar__systems
Вообще это довольно дерзко, не особо и в С понимая, вот так сходу брать и обвинять LwIP в глючности. Я бы посоветовал брать за аксиому, что там все правильно, а если вам кажется иначе, искать ошибки в вашем понимании С вообще и программы в частности.
AleksBak
Цитата(ar__systems @ Apr 8 2016, 18:08) *
Вообще это довольно дерзко, не особо и в С понимая, вот так сходу брать и обвинять LwIP в глючности. Я бы посоветовал брать за аксиому, что там все правильно, а если вам кажется иначе, искать ошибки в вашем понимании С вообще и программы в частности.

А Вы в C понимаете?? bb-offtopic.gif Тогда бы и объяснили чего и как . Тут объяснили. bb-offtopic.gif Мне люди тут и объяснили подробно и доходчиво - свое время потратили и ссылку привели и не одну. Вот им сто раз спасибо готов говорить за это (только так и могу - форум ведь все-таки тут). А Вы вот только под конец написали свое мнение по-этому поводу. Резюме так сказать. И что же? bb-offtopic.gif bb-offtopic.gif Вот что. А вообще такое предвзятое отношение к этому LwIP у меня не просто так, а вот стал проверять его работу и что-то нестабильной она показалась сильно. Стал изучать потихоньку что и как и вот в этой теме и спросил один из моментов при этом. В разделе "Для начинающих" между прочим. Ну не приходилось мне особо применять динам. выделение памяти (может даже и к лучшему это вообще-то т.к. темный лес еще тот).

У меня другой сетевой стек работал месяцами не выключаясь. Больше полгода - точно было, а больше не получилось только потому что отключали для плановой замены буферного акк-ра или когда ремонт делали в комнате. А вот насчет LwIP-а что-то я совсем не уверен, что такое будет. Вообще не уверен. Поживем - увидим как говорится.
ar__systems
Цитата(AleksBak @ Apr 8 2016, 12:24) *
У меня другой сетевой стек работал месяцами не выключаясь. Больше полгода - точно было, а больше не получилось только потому что отключали для плановой замены буферного акк-ра или когда ремонт делали в комнате. А вот насчет LwIP-а что-то я совсем не уверен, что такое будет. Вообще не уверен. Поживем - увидим как говорится.


Я да, понимаю, и в LWIP тоже. Он у меня тоже по полгода работает. Есть нюансы конечно, но для embedded stack пойдет.
jcxz
Цитата(AleksBak @ Apr 8 2016, 23:24) *
А Вы в C понимаете?? bb-offtopic.gif Тогда бы и объяснили чего и как . Тут объяснили. bb-offtopic.gif Мне люди тут и объяснили подробно и
...
В разделе "Для начинающих" между прочим. Ну не приходилось мне особо применять динам. выделение памяти (может даже и к лучшему это вообще-то т.к. темный лес еще тот).

Если Вы не можете разобраться в паре строк простого кода, то очевидно, советовать можно только изучать учебник по си - все остальные советы бессмысленны.
Да и разделом Вы ошиблись, тут где-то был раздел "Для совсем начинающих", Вам туда, пока язык не изучите.
Динамическим выделением памяти и кучей в исходной функции даже не пахнет. Откуда Вы его постоянно приплетаете? Создаётся впечатление, что Вы не знаете что это такое, как впрочем и что такое "локальная переменная".
В исходной функции идёт обычный возврат данных через указатель. Если даже такое не понятно - только учебник.
AleksBak
Цитата(jcxz @ Apr 10 2016, 12:18) *
...
Динамическим выделением памяти в исходных функциях даже не пахнет...

Что Вы говорите? biggrin.gif Неужели??? Тут значит уже статическое выделение памяти под переменную? Да ну?? Мне тут люди уже ответили и пояснили популярно что и как и где я был не прав. Все я признаю и благодарен им. А Вы можете дальше не пояснять т.к. толку будет абсолютный нуль. Неделю назад Вы конкретно заявили, что STM32F030 это Cortex-M3 серия и что? Запомнил как раз Ваш пост и ник (!). Еще раз повторяю для любителей впустую писать - мне тут все ответили люди и пояснили. Огромное спасибо им. И все. Понятно да?
jcxz
Цитата(AleksBak @ Apr 10 2016, 14:31) *
Что Вы говорите? biggrin.gif Неужели??? Тут значит уже статическое выделение памяти под переменную? Да ну??

Ни динамических ни статических выделений памяти там вообще нет никаких. Ни одного.

Цитата(AleksBak @ Apr 10 2016, 14:31) *
Неделю назад Вы конкретно заявили, что STM32F030 это Cortex-M3 серия и что? Запомнил как раз Ваш пост и ник (!).

Ложь. Cortex-M3 - это не серия (серия чего???), это ядро.
И утверждать на каком ядре построен STM32F030 я не мог, так как не знаю этого, и мне это не интересно.

PS: Очевидно Вы даже читать не умеете, то что Вам написали.
AleksBak
Цитата(jcxz @ Apr 10 2016, 12:45) *
Выделений памяти там вообще нет никаких. Ни одного.
...

Поясню как это все работает :
Код
struct netconn *newconn;

тут мы фактически выделили память под структуру типа netconn (ее описание см. тут же в этой теме), а далее тут передаем:
sys_arch_mbox_fetch(&conn->acceptmbox, (void **) &newconn, 0);
мы ждем прихода элемент в очередь сообщений и как оно там появится, то его содержимое будет скопировано в выделенный буфер под него т.е. по указателю newconn будет скопирована вся такая структура (ее описание см. тут в этой теме). А функция sys_arch_mbox_fetch эта обертка под получение этого элемента очереди в ОС. А насчет ядра и серии - да я очень грубо ошибся и не пойму как такое слово мог написать. Ядро конечно это. Еще какие ошибки у меня тут есть?? Мне значит тогда совсем закопаться и в школу пойти так да? Вот я сижу-пишу как дурак эти строчки, чего-то доказываю, а двое спиногрызов (дети) реально в этот момент меня задалбливают. cranky.gif Один со своими машинками лезет, а другая чем-то недовольна и кричит громко в ответ.
aaarrr
Цитата(AleksBak @ Apr 10 2016, 12:19) *
Код
struct netconn *newconn;

тут мы фактически выделили память под структуру типа netconn

Нет, ничего не выделили. Создали локальный указатель на структуру данного типа.
jcxz
Цитата(AleksBak @ Apr 10 2016, 15:19) *
Поясню как это все работает :
Код
struct netconn *newconn;

тут мы фактически выделили память под структуру типа netconn (ее описание см. тут же в этой теме), а далее тут передаем:
sys_arch_mbox_fetch(&conn->acceptmbox, (void **) &newconn, 0);
мы ждем прихода элемент в очередь сообщений и как оно там появится, то его содержимое будет скопировано в выделенный буфер под него т.е. по указателю newconn будет скопирована вся такая структура (ее описание см. тут в этой теме).

struct netconn *newconn; - это не выделение памяти под структуру, это объявление указателя на структуру.
Вот для того, чтобы понять разницу между объектом и указателем на него, Вам и стоит открыть учебник.
Никаких копирований содержимого структуры там не может происходить. sys_arch_mbox_fetch просто сохраняет в newconn указатель на некий экземпляр структуры struct netconn (либо сохраняет там NULL). Где этот экземпляр находится, из этого кода неясно. Он может находиться как в динамической памяти так и в статической и даже в автоматической (на стеке). Это узнать можно только смотря код sys_arch_mbox_fetch.
AleksBak
Цитата(jcxz @ Apr 10 2016, 13:32) *
...Где этот экземпляр находится, из этого кода неясно. Он может находиться как в динамической памяти так и в статической и даже в автоматической (на стеке). Это узнать можно только смотря код sys_arch_mbox_fetch.

Код
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
{
    void *dummyptr;
    portTickType StartTime, EndTime, Elapsed;

    StartTime = xTaskGetTickCount();

    if (msg == NULL)
    {
        msg = &dummyptr;
    }

    if (timeout != 0)
    {
        if ( pdTRUE == xQueueReceive(*mbox, &(*msg), timeout / portTICK_RATE_MS))
        {
            EndTime = xTaskGetTickCount();
            Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;

            return (Elapsed);
        }
        else // timed out blocking for message
        {
            *msg = NULL;

            return SYS_ARCH_TIMEOUT;
        }
    }
    else // block forever for a message.
    {
        while ( pdTRUE != xQueueReceive(*mbox, &(*msg), portMAX_DELAY))
        {
        } // time is arbitrary
        EndTime = xTaskGetTickCount();
        Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;

        return (Elapsed); // return time blocked TODO test
    }
}

Тут параметр - timeout передается равным нулю напоминаю. Вообще все это по-хорошему если, то переписать/переделать нужно. А Вы вообще этот NetConn используете? Или кто из зала тут использует? Если посмотреть, то получается что тут по приходу коннекта снаружи, мы получаем из очереди сообщений ОС (xQueueReceive) всю структуру - копированием по указателю в выделенный для этого буфер (т.е по указателю newconn находится выделенный буфер). То что мне нужно учебники читать и в школу идти - это понятно, только не надо это в каждом посту писать. Расслабьтесь. Я вот терплю своих реально спиногрызов же сейчас и пытаюсь их уложить спать (сейчас время). 1111493779.gif Посмотрите свысока на ученика более спокойно.

Цитата(jcxz @ Apr 10 2016, 13:32) *
...
Никаких копирований содержимого структуры там не может происходить. sys_arch_mbox_fetch просто сохраняет в newconn указатель на некий экземпляр структуры struct netconn (либо сохраняет там NULL)...

Еще раз коротко поясню (по-моему мнению конечно): там, дальше используется функция ОС (FreeRTOS тут ясень пень) получения элемента из очереди сообщений - функция xQueueReceive. С одновременным удалением этого элемента из очереди. В эту функцию мы должны в 1-ом параметре передать дескриптор очереди, во 2-м параметре передается указатель на область памяти куда будет скопирован элемент, а в третьем параметре передается время ожидания появления этого элемента в очереди (время блокирования задачи) - если этот параметр равен portMAX_DELAY, то ждем бесконечно долго. Я сейчас должен пойти на базар чтобы купить смеситель/гибкий шланг взамен неисправных и меня наверно час 2-3 не будет - поэтому тут еще раз пояснил и дополнил сейчас на всякий случай. Спасибо.
jcxz
Цитата(AleksBak @ Apr 10 2016, 16:23) *
этот NetConn используете? Или кто из зала тут использует? Если посмотреть, то получается что тут по приходу коннекта снаружи, мы получаем из очереди сообщений ОС (xQueueReceive) всю структуру - копированием по указателю в выделенный для этого буфер (т.е по указателю newconn находится выделенный буфер). То что мне нужно учебники читать и в школу идти - это понятно, только не надо

Опять 25..... twak.gif
Ещё раз: из кода ясно видно, что xQueueReceive() записывает в *msg указатель (дважды выделить!!!) на некую структуру в памяти, но не саму структуру. Никаких копирований структур она не делает и в принципе делать не может, так как даже не знает размера объекта, на который указывает возвращаемый ею указатель (она возвращает указатель типа void *). xQueueReceive() без разницы тип и размер данных, на которые она указывает, для мэйлбоксов это и не нужно. Возвращается просто указатель! Указатель - это просто переменная размера sizeof(int) (обычно), это просто одно число.
Т.е. - после возврата из sys_arch_mbox_fetch(), в вызывающей функции, переменная newconn будет равна полученному из xQueueReceive() указателю (если конечно xQueueReceive() вернула true).
AleksBak
Цитата(jcxz @ Apr 10 2016, 15:38) *
Опять 25..... twak.gif
...

Указатель так указатель. Что веткой драться то. И еще толстой такой веткой. Нет чтобы потоньше веточка, а то дубинка какая-то. И в самом деле - это ведь просто переменная указателя на какую-то без разницы даже какую память. Что я так зациклился на том что и память куда он показывает обязательно должна быть уже тут сразу заполнена и показывать на готовую структуру на выходе. На выходе то она готовая может быть (или сам указатель равен NULL), но не на этом шаге она заполняется. А заполняется она в другом месте программы. Меня просто с толку сбил механизм работы этой очереди и все прицепился, что при получении элемента из очереди будет происходить копирование в выделенный буфер содержимого. Копирование просто указателя на то место в памяти где они (структуры) появляются. И даже думал почему так непродуктивно работает это? Туда-сюда данные копируются с одного места в другое. Надо бы посмотреть как там все это происходит. В какой части памяти все это пишется. И какая память и т.п. А Вы вообще NetConn API используете? Что-нибудь хорошего плохого можете о нем сказать? Я кстати купил для ванной запчасти. Еще и дома успели поспорить по поводу одежды и пр. А у Вас как дела вообще?

Цитата(jcxz @ Apr 10 2016, 15:38) *
... для мэйлбоксов это и не нужно....

Еще вот позанудствую насчет слова мэйлбокс - это же в дословном переводе как "очередь сообщений" переводится? Так ведь? Так же проще понимать. Или все-таки это не "очередь сообщений" в данном случае, а что-то необычное тут?
gosha-z
MailBox - почтовый ящик.
MessageQueue - очередь сообщений
AleksBak
Опять я ошибся и перепутал - не "очередь сообщений", а "буфер сообщений" (про него изначально думал) Так переводится это словосочетание тут вроде. Так же легче понимать.
ar__systems
Цитата(AleksBak @ Apr 10 2016, 04:19) *
Поясню как это все работает :
Код
struct netconn *newconn;

тут мы фактически выделили память под структуру типа netconn (ее описание см. тут же в этой теме), а далее тут передаем:
sys_arch_mbox_fetch(&conn->acceptmbox, (void **) &newconn, 0);
мы ждем прихода элемент в очередь сообщений и как оно там появится, то его содержимое будет скопировано в выделенный буфер под него т.е. по указателю newconn будет скопирована вся такая структура (ее описание см. тут в этой теме). А функция sys_arch_mbox_fetch эта обертка под получение этого элемента очереди в ОС. А насчет ядра и серии - да я очень грубо ошибся и не пойму как такое слово мог написать. Ядро конечно это. Еще какие ошибки у меня тут есть?? Мне значит тогда совсем закопаться и в школу пойти так да? Вот я сижу-пишу как дурак эти строчки, чего-то доказываю, а двое спиногрызов (дети) реально в этот момент меня задалбливают. cranky.gif Один со своими машинками лезет, а другая чем-то недовольна и кричит громко в ответ.


Чукча не читатель, чукча писатель?

Извините, но очевидно, все что вам писали выше прошло мимо и вы продолжаете писать полную ерунду. Какой lwip, о чем вы? Берите учебник "с для чайников" и начинайте с самых азов, hello world итд
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.