由于我在Java中习惯大量使用String类,所以转到C++下,自然也想使用STL的string。写了一个startWith函数,并在程序中多次使用。
bool startWith(string longString, string shortString)
{
returnlongString.find(shortString) == 0;
}
程序单元测试无误,但在集成测试时,遇到了不确定出现的缺陷。全局静态的list中的内容似乎被访问越界给改写了,然后我们集中寻找哪里出现访问越界。但在后来的反复测试中发现,甚至在简单的string赋值时,都会出现内存分配错误。于是我们开始怀疑string。在网上一查,发现
有贴子讨论过C++的string是线程不安全的。这样测试中的种种现象就可以解释了。于是写了个多线程测试来压startWith,果然重现问题。然后重写了startWith函数。在参数中使用string类型,都会因为传递时需要拷贝而变得线程不安全。
bool startWith(const char *
longString, constchar *
shortString) {
assert(strlen(longString) < 1000);
assert(strlen(shortString) < 1000);
char ls[1000];
char ss[1000];
strcpy(ls,
longString);
strcpy(ss,
shortString);
char * cp1 = ls;
char * cp2 = ss;
while(*cp2 !='\0')
{
if (*cp1 == *cp2)
{
cp1++;
cp2++;
} else {
returnfalse;
}
}
return true;
}
总结:
- string装得像个栈变量,但却操作堆空间,而且线程不安全
- 线程是否安全应该属于使用契约,如何通过防御式设计来避免?
- 集成测试应该尽早进行
- 不确定出现的缺陷大多与多线程有关
- 不了解原理的复用,可能降低软件开发的效率和品质
- 从一个侧面理解了为什么Linus要炮轰C++
- 这段c代码不好看,怎样写得好看些?