昨天经理跟我说发现一个问题,有个树里面的叶子的显示有问题,本来应该是这样的:
网块1
--网元1
--网元2
网块2
--网元1
--网元2
但是现在却变成这样了:
网块2
--网元1
--网元2
网块2
--网元1
--网元2
而以前一直都是好的,这是怎么回事呢?
从版本控制器里面看到这个部分的代码在4月份的时候有过一次修改。
for (int i=0;i<arPartID.GetSize();i++)
{
char bfPart[40];
int j=arPartID.GetAt(i);
int iErrorCode =oEngine.ORGetPartData(j,"%partname",bfPart);
CStringArray* pArray=new CStringArray();
pArray->Add(bfPart);
......
s_data.Add(pArray);
}
现在的代码是:
for (int i=0;i<arPartID.GetSize();i++) 1
{ 2
CString strPartName; 3
int j=arPartID.GetAt(i); 4
int iErrorCode =oEngine.ORGetPartName(j,strPartName); 5
CStringArray* pArray=new CStringArray(); 6
pArray->Add(strPartName); 7
......
s_data.Add(pArray);
}
当时改动的目的是这个适配器函数oEngine::ORGetPartName的接口变了,所以想着要变CString就一起变吧。找到是由于这个变化引起的问题后,我写了一个Trace的函数,跟踪s_data的变化。一行行的看,最后终于发现问题了!
这个循环执行第一遍的时候没什么异常,第二遍执行到第5行后,s_data里面的“网块1”,突然变成了“网块2”。
研究一阵子才发现,原来CString在使用无参数的构造函数时:
CString::CString()
{
Init();
}
而
_AFX_INLINE void CString::Init()
{ m_pchData = afxEmptyString.m_pchData; }
而
#define afxEmptyString ((CString&)*(CString*)&_afxPchNil)
而
// afxChNil is left for backward compatibility
AFX_DATADEF TCHAR afxChNil = '/0';
现在就很清楚了,当使用使用无参数的构造函数时,CString是将自己m_pchData统一指向MFC定义的一个指针afxChNil 的,而像我那样在构造函数之后马上将CString当成字符串指针使用,其结果是我修改了MFC内部定义的afxChNil 的值。然后,我再构造另一个无参数CString时,它立刻就被赋值成前一个值了。如果我还照旧在构造函数之后马上将CString当成字符串指针使用,其结果是我得到了两个值一样的CString。
不知道我说明白了没有,简单一点的测试代码可能是这样的:
const CString A="A"; 1
const CString B="B"; 2
CString str1; 3
strcpy(str1,A); 4
CString str2; 5
strcpy(str2,B); 6
预期效果是执行到第六行,str1也变成了"B"。不过这点代码无法执行,因为strcpy不支持将CString转化成char *。这就需要你自己写一个类似的拷贝函数,我使用的那个oEngine::ORGetPartName里面就调了一个这样的函数:int GetPartData( int PartID, const char *formatstring,... );
这样的函数现在好像不是很常用了,因为不进行严格的参数检查很容易出错。
好吧,就算是我的拷贝函数用错了,但是微软怎么就不能把它那个该死的afxChNil定义成常量呢。那我不是马上就知道有问题了吗,唉,以前总是听别人说CString不好用,但没有体验过,今天我算是领教了!