前言
最近,在项目里遇到一个很 “诡异” 的问题。明明把后面需要使用的值存起来了,可是使用的时候,却拿到了一堆垃圾数据。有可能是什么原因呢?一起来看看吧。
调查思路
这种问题排查起来比较简单。可以依次排查以下几个地方:
- 保存代码是否正确。
- 读取代码是否正确。
- 在保存后,读取前是否有其它代码修改了保存的值。
按照这个思路,很快定位到问题出在第一步,也就是保存的时候出了问题。
为了让各位小伙伴儿也能实际感受这个问题,我特意模仿实际项目中的代码写了一份可以重现的代码。
关键代码
AdjustInfoByteConverter
里的代码比较简单,而且已经验证过没问题,这就不贴了。感兴趣的小伙伴儿可以下载示例工程查看完整代码。
调用代码如下:
1 |
|
说明:
在实际排查问题的时候我就是这样缩小排查范围的,调用完
SetAdjustInfo()
,直接调用GetAdjustInfo()
,查看两次结果是否一致。这样可以很快缩小需要排查的范围。在写完
AdjustInfoByteConverter::ToBytes
和AdjustInfoByteConverter::FromBytes
的实现后,也用了类似的办法做了验证,所以在实际项目中直接排除了这两个函数的嫌疑。
CDemoObject
类的实现如下,很规矩。
1 |
|
有瑕疵的代码如下,但并不是所有情况下都有问题,你能找出这个问题吗?
1 |
|
根本原因
这个问题的根本原因在于:调用了错误的 PropertyValue
构造函数。
预期被调用的函数是 PropertyValue(std::vector<byte>& value)
,而实际调用的函数却是 template<class T> PropertyValue(T value)
。
因为 CDemoObject
类的 void SetAdjustInfo(const std::vector<byte>& bytes)
函数的参数是 const
的。在编译 PropertyValue value(bytes);
这行代码的时候,需要找到一个最优的构造函数,最终找到的是 template
版本的。不能把一个 const
对象丢给一个参数是非 const
的函数!
解决方案
这个问题解决起来很简单,有两种改法:
- 去掉
const
对象的const
属性。 - 改动底层代码,把非
const
版本改成const
版本的函数。
实际项目中采用的第一种改法,因为没有权限改动底层接口,但这种改法治标不治本。
下载链接
百度云盘链接: 链接: https://pan.baidu.com/s/1a2p9YWPLtlOe6dM_j_s80w 提取码: j96h
CSDN:https://download.csdn.net/download/xiaoyanilw/14965002
总结
- 尽量使用引用传递类对象,而且如果不想在函数内部修改这个对象的话,务必加上
const
。 - 不能把一个
const
对象丢给一个非const
参数的函数。 - 排查问题的时候,尽可能的缩小范围。