Skip to content

Conversation

@A2va
Copy link
Contributor

@A2va A2va commented Nov 25, 2024

  • Before adding new features and new modules, please go to issues to submit the relevant feature description first.
  • Write good commit messages and use the same coding conventions as the rest of the project.
  • Please commit code to dev branch and we will merge into master branch in feature
  • Ensure your edited codes with four spaces instead of TAB.

  • 增加新特性和新模块之前,请先到issues提交相关特性说明,经过讨论评估确认后,再进行相应的代码提交,避免做无用工作。
  • 编写友好可读的提交信息,并使用与工程代码相同的代码规范,代码请用4个空格字符代替tab缩进。
  • 请提交代码到dev分支,如果通过,我们会在特定时间合并到master分支上。
  • 为了规范化提交日志的格式,commit消息,不要用中文,请用英文描述。

@waruqi
Copy link
Member

waruqi commented Nov 26, 2024

error: buffer.c
src\tbox\stream\impl\stream\buffer.c(143): error C2220: the following warning is treated as an error
src\tbox\stream\impl\stream\buffer.c(143): warning C4244: '=': conversion from 'tb_hize_t' to 'tb_size_t', possible loss of data

@waruqi waruqi merged commit 7ebe9d7 into tboox:dev Nov 27, 2024
11 of 13 checks passed
@A2va A2va deleted the buffer-stream branch November 27, 2024 09:27
@duyanning
Copy link
Contributor

duyanning commented Jun 26, 2025

目前这个实现,tb_stream_exit时会连带buffer一起销毁。

建议不要连带buffer一起销毁。

理由如下:

如果我在函数 f 中产生一个buffer,并通过stream向其中写入了一些东西,然后我想返回这个buffer。
现在就遇到麻烦了:
如果我tb_stream_exit这个stream,buffer也就没了,无法返回。
我为了返回只能选择不tb_stream_exit这个stream,那样stream又得不到销毁。

我看了一下,可能是个bug:

    case TB_STREAM_CTRL_BUFF_SET_BUFFER:
        {
            // exit buffer first if exists
            if (stream_buffer->buffer && !stream_buffer->bref) tb_buffer_exit(stream_buffer->buffer);

            stream_buffer->buffer = (tb_buffer_ref_t)tb_va_arg(args, tb_buffer_ref_t);
            stream_buffer->head  = 0;
            stream_buffer->bref = tb_false;    // 此处应赋值为tb_true
            return tb_true;
        }

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


In this implementation, tb_stream_exit will be destroyed together with buffer.

It is recommended not to destroy buffers together.

The reasons are as follows:

If I produce a buffer in function f and write something to it via stream, then I want to return this buffer.
Now I'm in trouble:
If I tb_stream_exit the stream, the buffer will be gone and I cannot return it.
In order to return, I can only choose not to tb_stream_exit, so the stream will not be destroyed.

@A2va
Copy link
Contributor Author

A2va commented Jun 26, 2025

I think you're right. My implementation is based off the data stream, where bref is true in this case, I don't recall if there was some reasoning to be false.

@waruqi
Copy link
Member

waruqi commented Jun 26, 2025

目前这个实现,tb_stream_exit时会连带buffer一起销毁。

建议不要连带buffer一起销毁。

理由如下:

如果我在函数 f 中产生一个buffer,并通过stream向其中写入了一些东西,然后我想返回这个buffer。 现在就遇到麻烦了: 如果我tb_stream_exit这个stream,buffer也就没了,无法返回。 我为了返回只能选择不tb_stream_exit这个stream,那样stream又得不到销毁。

我看了一下,可能是个bug:

    case TB_STREAM_CTRL_BUFF_SET_BUFFER:
        {
            // exit buffer first if exists
            if (stream_buffer->buffer && !stream_buffer->bref) tb_buffer_exit(stream_buffer->buffer);

            stream_buffer->buffer = (tb_buffer_ref_t)tb_va_arg(args, tb_buffer_ref_t);
            stream_buffer->head  = 0;
            stream_buffer->bref = tb_false;    // 此处应赋值为tb_true
            return tb_true;
        }

目前这个实现,tb_stream_exit时会连带buffer一起销毁。

建议不要连带buffer一起销毁。

理由如下:

如果我在函数 f 中产生一个buffer,并通过stream向其中写入了一些东西,然后我想返回这个buffer。 现在就遇到麻烦了: 如果我tb_stream_exit这个stream,buffer也就没了,无法返回。 我为了返回只能选择不tb_stream_exit这个stream,那样stream又得不到销毁。

我看了一下,可能是个bug:

    case TB_STREAM_CTRL_BUFF_SET_BUFFER:
        {
            // exit buffer first if exists
            if (stream_buffer->buffer && !stream_buffer->bref) tb_buffer_exit(stream_buffer->buffer);

            stream_buffer->buffer = (tb_buffer_ref_t)tb_va_arg(args, tb_buffer_ref_t);
            stream_buffer->head  = 0;
            stream_buffer->bref = tb_false;    // 此处应赋值为tb_true
            return tb_true;
        }

right, you can open a pr to fix it.

@waruqi
Copy link
Member

waruqi commented Jun 27, 2025

I have fixed it.

@duyanning
Copy link
Contributor

duyanning commented Oct 8, 2025

这是否一个bug,请确认一下:
我用tb_stream_init_from_buffer创建了一个挂在buffer上的流,
我打算在这个buffer构造一个数据包裹,包裹的第一个字段是载荷的大小,
但这个载荷大小在包裹完全构造出来后才能确定,所以我就在载荷大小字段位置处暂时填了0:

    // 因为这个包裹的载荷大小不固定,所以先将其在内存缓冲区中构造出来
    tb_buffer_ref_t parcel_buf = tb_malloc0_type(tb_buffer_t);
    tb_buffer_init(parcel_buf);
    tb_stream_ref_t ostream_to_parcel_buf = tb_stream_init_from_buffer(parcel_buf);
    tb_stream_open(ostream_to_parcel_buf);

    logger_print("debug:buffer size1:%d", tb_buffer_size(parcel_buf));   // 输出0

    // 载荷大小此时尚不能确定,先跳过
    // tb_stream_skip(ostream_to_parcel_buf, 4); // 由于tb_stream_skip的内部实现,写位置无法超过缓冲区当前大小
    tb_stream_bwrit_s32_be(ostream_to_parcel_buf, 0); // 只能通过写入无效数据来达到效果
 
    // 继续通过流向缓冲区中写入其他字段
   // 省略若干行

    // 此时载荷大小可以确定了,跳到包裹头部(偏移量:0)写入载荷大小
    logger_print("debug:buffer size5:%d", tb_buffer_size(parcel_buf)); // 输出428
    tb_stream_seek(ostream_to_parcel_buf, 0);
    logger_print("debug:buffer size6:%d", tb_buffer_size(parcel_buf)); // 输出428
    tb_stream_bwrit_s32_be(ostream_to_parcel_buf, 2+4+data_len);  // 这个函数最终会调用tb_stream_buffer_writ
    logger_print("debug:buffer size7:%d", tb_buffer_size(parcel_buf)); // 输出4 (令人意外)
       

我看了一下源码

static tb_long_t tb_stream_buffer_writ(tb_stream_ref_t stream, tb_byte_t const* data, tb_size_t size)
{
    tb_stream_buffer_t* stream_buffer = tb_stream_buffer_cast(stream);
    tb_assert_and_check_return_val(stream_buffer && stream_buffer->buffer, -1);

    tb_check_return_val(data, -1);
    tb_check_return_val(size, 0);

    if (size) tb_buffer_memncpyp(stream_buffer->buffer, stream_buffer->head, data, size);  // 注意此处,head为0,size为4
    stream_buffer->head += size;
    return size;
}

而tb_buffer_memncpyp调用了tb_buffer_resize,这个函数会把缓冲区缩小

tb_byte_t* tb_buffer_memncpyp(tb_buffer_ref_t buffer, tb_size_t p, tb_byte_t const* b, tb_size_t n)
{
    // check
    tb_assert_and_check_return_val(buffer && b, tb_null);

    // check
    tb_check_return_val(n, tb_buffer_data(buffer));

    // resize
    tb_byte_t* d = tb_buffer_resize(buffer, p + n);  // 注意此处,p为0,n为4
    tb_assert_and_check_return_val(d, tb_null);

    // copy it
    tb_memcpy(d + p, b, n);

    // ok
    return d;
}

感觉有点反直觉。
如果就是这样设计的,请问有没有什么推荐的办法来达到我在缓冲区中回填载荷大小字段的目的?

@waruqi
Copy link
Member

waruqi commented Oct 8, 2025

tb_buffer_memncpyp 是覆盖重写 buffer 所以每次调用,都是会重新计算当前的实际大小

这里得用 tb_buffer_resize + tb_memcpy 来做。你可以提 pr 改进下

@Issues-translate-bot
Copy link

Bot detected the issue body's language is not English, translate it automatically.


tb_buffer_memncpyp overwrites and rewrites buffer, so every time it is called, the current actual size will be recalculated.

You have to use tb_buffer_resize + tb_memcpy to do this. You can submit a PR to improve it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants