2881099 / csredis

.NET Core or .NET Framework 4.0+ client for Redis and Redis Sentinel (2.8) and Cluster. Includes both synchronous and asynchronous clients.
MIT License
2.01k stars 414 forks source link

ReadLine()判断不严谨,导致内存暴增问题 #509

Closed HaibaraAi119 closed 4 months ago

HaibaraAi119 commented 4 months ago

public int ReadByte() { lock (_streamLock) { return Stream.ReadByte(); } } public virtual int ReadByte() { byte[] array = new byte[1]; if (Read(array, 0, 1) != 0) { return array[0]; } return -1; } private string ReadLine() { if (!_io.Stream.CanRead) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); bool flag = false; while (true) { char c = (char)_io.ReadByte(); if (c == '\r') { flag = true; continue; } if (c == '\n' && flag) { break; } stringBuilder.Append(c); flag = false; } return stringBuilder.ToString(); } 我在某些网络异常,或者,redis出现访问问题,重启redis时出现 ReadLine()似乎并没有对ReadByte()返回-1进行判断,导致误读大量脏数据,导致内存暴增, 我在dump分析下查看此部分内存情况,如图: image

2881099 commented 4 months ago

感谢反馈,csredis底层通讯模块是国外人写的,您可以进行PR或者等待这边修复新版

2881099 commented 4 months ago

有机会可以切换到 FreeRedis,是吸取经验后完全重写的开源项目。

https://github.com/2881099/FreeRedis

HaibaraAi119 commented 4 months ago

感谢反馈,csredis底层通讯模块是国外人写的,您可以进行PR或者等待这边修复新版 建议进行如下修改,以保证判断严谨 private string ReadLine() { if (!_io.Stream.CanRead) { return string.Empty; } StringBuilder stringBuilder = new StringBuilder(); bool flag = false; int c = -1; while ((c = _io.ReadByte()) != -1) { if ((char)c == '\r') { flag = true; continue; } if (((char)c == '\n') || ((char)c == '\n' && flag)) { break; } stringBuilder.Append((char)c); flag = false; } return stringBuilder.ToString(); }

2881099 commented 4 months ago

v3.8.803 #510