Bug: dkapture::read() 两个 vector 重载返回“剩余缓冲区大小”而非“已读字节数”
- 文件:
so/dkapture.cpp
- 行号: 127-141 与 143-157
- 影响: API 返回值语义错误,调用方无法得到实际读取的数据量
现象 / 问题描述
include/dkapture.h(bpf/export/dkapture.h)中这两个重载的接口契约都写明:
@return 成功返回读取的字节数,失败返回 -errno
virtual ssize_t read(std::vector<DataType> &dts, pid_t pid, DataHdr *buf, size_t bsz) = 0;
virtual ssize_t read(std::vector<const char *> &paths, DataHdr *buf, size_t bsz) = 0;
但实现却返回了 剩余缓冲区大小 bsz(即初始容量减去已写入的字节数),而不是已写入的字节数:
ssize_t dkapture::read(std::vector<DataType> &dts, pid_t pid, DataHdr *buf, size_t bsz)
{
for (auto dt : dts)
{
ssize_t ret = read(dt, pid, buf, bsz);
if (ret < 0) continue;
buf = (DataHdr *)((char *)buf + ret);
bsz -= ret;
}
return bsz; // BUG: 返回的是剩余空间
};
ssize_t dkapture::read(std::vector<const char *> &paths, DataHdr *buf, size_t bsz)
{
for (auto path : paths)
{
ssize_t ret = read(path, buf, bsz);
if (ret < 0) continue;
buf = (DataHdr *)((char *)buf + ret);
bsz -= ret;
}
return bsz; // BUG: 返回的是剩余空间
};
对照同文件内语义正确的重载(返回实际写入字节数):
ssize_t dkapture::read(DataType dt, std::vector<pid_t> &pids, DataHdr *buf, size_t bsz)
{
ssize_t dsz = bsz;
...
return dsz - bsz; // 正确:返回已读字节数
};
影响
- 调用方按文档用返回值判断读取量/遍历数据时会得到错误结果:返回的是“还剩多少空间”,而不是“写了多少字节”;
- 例如:
bsz = 1MB,只读了一个 DataHdr + ProcPidStat(几十字节),返回值 ≈ 1MB,而不是实际字节数;
- 当
bsz 减到 0 后再次调用时还会返回 0,进一步混淆“读到了 0 字节”与“缓冲区已满”。
复现步骤
DKapture *dk = DKapture::new_instance(); dk->open(...);
std::vector<DKapture::DataType> dts = {PROC_PID_STAT};
ssize_t ret = dk->read(dts, 1, buf, 1024*1024);
- 观察:
ret 远大于实际写入 buf 的字节数(应等于 sizeof(DataHdr)+sizeof(ProcPidStat) 左右)。
期望行为
累加实际写入的字节数并返回,例如:
ssize_t dkapture::read(std::vector<DataType> &dts, pid_t pid, DataHdr *buf, size_t bsz)
{
size_t total = 0;
for (auto dt : dts)
{
ssize_t ret = read(dt, pid, buf, bsz);
if (ret <= 0) continue;
assert((size_t)ret <= bsz);
total += ret;
bsz -= ret;
buf = (DataHdr *)((char *)buf + ret);
}
return total;
}
环境信息
- 分支: master (
8cdb788)
- 相关 PR/Issue: 未发现已有相同问题
Bug:
dkapture::read()两个 vector 重载返回“剩余缓冲区大小”而非“已读字节数”so/dkapture.cpp现象 / 问题描述
include/dkapture.h(bpf/export/dkapture.h)中这两个重载的接口契约都写明:但实现却返回了 剩余缓冲区大小
bsz(即初始容量减去已写入的字节数),而不是已写入的字节数:对照同文件内语义正确的重载(返回实际写入字节数):
影响
bsz = 1MB,只读了一个DataHdr + ProcPidStat(几十字节),返回值 ≈ 1MB,而不是实际字节数;bsz减到 0 后再次调用时还会返回 0,进一步混淆“读到了 0 字节”与“缓冲区已满”。复现步骤
DKapture *dk = DKapture::new_instance(); dk->open(...);std::vector<DKapture::DataType> dts = {PROC_PID_STAT};ssize_t ret = dk->read(dts, 1, buf, 1024*1024);ret远大于实际写入buf的字节数(应等于sizeof(DataHdr)+sizeof(ProcPidStat)左右)。期望行为
累加实际写入的字节数并返回,例如:
环境信息
8cdb788)