如何使用 flex 和 bison 解析非常大的缓冲区
How to parse very large buffer with flex and bison
我写了一个json库,它使用flex和bison来解析序列化的json(即字符串),并将它们反序列化为json对象。它非常适合小字符串。
但是,它无法处理非常大的字符串(我尝试了几乎 3 GB
的字符串),并出现此错误:
‘fatal flex scanner internal error--end of buffer missed’
我想知道我可以传递给此函数的缓冲区的最大大小是多少:
//js: serialized json stored in std::string
yy_scan_bytes(js.data(), js.size());
如何使 Flex/Bison 与大型缓冲区一起工作?
,您使用的是旧版本的 flex 骨架(因此也是 flex),其中假定字符串长度适合 int
s。您观察到的错误消息可能是int
溢出到负值的结果。
我相信,如果您切换到 2.5.37 或更高版本,您会发现这些int
中的大多数都已变得size_t
,使用大小超过 2 GB 的输入缓冲区调用 yy_scan_bytes
应该没有问题。(例如,该函数的原型现在采用size_t
而不是int
。
然而,我很难相信这样做是个好主意。首先,yy_scan_bytes
复制整个字符串,因为词法扫描程序想要一个允许修改的字符串,并且因为它希望确保字符串末尾有两个 NUL 字节。制作该副本将不必要地消耗大量内存,如果您无论如何都要复制缓冲区,您不妨将其复制为可管理的片段(例如,64Kib 甚至 1MiB)。只有当你的单个代币明显大于块大小时,这才会有问题,因为flex绝对没有针对大型单个代币进行优化。但是对于所有正常的用例,它可能会做得更好。
Flex 不提供将巨大的输入缓冲区拆分为块的接口,但您可以通过重新定义YY_INPUT
宏来非常轻松地做到这一点。(如果这样做,最终可能会使用 yyin
作为指向您自己的缓冲区结构的指针,该结构理论上是不可移植的。但是,它将适用于任何 Posix 体系结构,其中所有对象指针都具有相同的表示形式。
当然,您通常不想等待内存中累积了 3GB 的数据才开始解析它。您可以在读取数据时以增量方式进行分析。(您可能仍需要重新定义YY_INPUT
,具体取决于您读取数据的方式。
- C++字符*缓冲区的大小
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- ostream过载时的缓冲区冲洗
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- Xaudio2在更改缓冲区或循环时弹出声音
- OpenGL大的3D纹理(>2GB)非常慢
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 如何在cpp.中使用协议缓冲区存储大缓冲区/数组(char/int)
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 多线程双缓冲区
- Android P-9.0.0_r53 Logcat主缓冲区超出定义大小
- 套接字读取后,我在缓冲区中看到意外输入
- 为什么std::互斥需要很长的、非常不规则的时间来共享
- std::带有自定义缓冲区的 iostream 不允许我写入
- 从返回的顶点缓冲区查询顶点结构
- 将 mmap 内存用于开销非常低的循环缓冲区
- 如何使用 flex 和 bison 解析非常大的缓冲区
- OpenGL帧缓冲区非常慢