Borland字符串::查找bug

Borland string::find bug

本文关键字:bug 查找 Borland 字符串      更新时间:2023-10-16

我支持使用Borland c++ Builder 5.02(从1997年开始)编写的c++应用程序。Borland字符串类上的find()方法的行为不符合我的预期:

#include <cstring>
#include <iostream>
int main (int argc, char *argv[])
{
   string needle = "length == eighteen";
   string haystack = "<" + needle + ">";
   if (haystack.find(needle) != NPOS)
      cout << "Found it!" << endl;
   else
      cout << "Not found" << endl;
   return 0;
}

程序输出Not found。如果我把针换成短点的,它输出Found it!。如果我把尖括号换成其他字符,它会找到它。空格可以用,但括号也不行。

请注意,我在这里使用Borland字符串库:如果我#include <string>并使用std::string,那么它的工作方式正是我所期望的。遗憾的是,将整个应用程序更改为使用STL字符串并不是一个可行的答案!

从文档中可以看出,Borland使用基于散列的算法进行字符串搜索。我找不到关于这个的更多细节,我已经完成了拆卸,但没有多少智慧。

我发现很难相信这真的是字符串库中的一个bug,特别是因为如果是的话,我希望能够找到一篇关于它的文章或其他东西。我找不到这样的资料。

然而,我已经没有主意了!这是已知的bug吗?有解决办法吗?

编辑:再次看了拆解,我认为它试图做一些像Rabin-Karp算法,其中哈希函数计算mod 33554393(最大的素数<2 ^ 25)。它很可能是一个以32为底的多项式哈希函数(即a_0 + 32 a_1 + 32^2 a_2 +…)+ 32^n a_n)不过这只是直觉。听起来像是Daniel Fischer建议的可能溢出

我发现了一个1998年的参考,建议Borland的搜索字符串的实现有一个错误:

https://groups.google.com/forum/?fromgroups= ! searchin bug/borland.public.cpp.language/装运箱20美元/borland.public.cpp.language/XBzjaJmCYpk/gtMPm-j8jugJ

而且,似乎在历史上的某个时刻,c++委员会决定将字符串类作为标准c++的一部分,而cstring的string类是这一点的残余:

https://groups.google.com/forum/?fromgroups= ! searchin/borland.public.cpp.language/宝蓝装运箱20美元/borland.public.cpp.language/2 psy2serms4/ywVrqwU1C2wJ

如果您使用的是原始的bc++ 5.02安装盘,则字符串类source在BC5 source RTL source string下。

下面是string::find_case_index()函数(由string::find()调用)的代码摘录:

const long q = 33554393L;
const long q32 = q<<5;
size_t testlength = length() - startindex;
size_t patternlength = patl = strlen(cp);
if( testlength < patternlength )
    return NPOS;
if( patternlength == 0 )
    return 0;
long patternHash = 0;
long testHash = 0;
const char _FAR *testP = c_str()+startindex;
const char _FAR *patP = cp;
long x = 1;
size_t i = patternlength-1;
while( i-- )
    x = (x<<5)%q;
for( i=0; i<patternlength; i++ )
    {
    patternHash = ( (patternHash<<5) + *patP++  ) % q;
    testHash    = ( (testHash   <<5) + *testP++ ) % q;
    }
testP = c_str()+startindex;
const char _FAR *end = testP + testlength - patternlength;
while (1)
    {
    if(testHash == patternHash)
        if( !get_paranoid_check_flag() ||
            !strncmp( testP, cp, patternlength) )
          return (size_t)(testP-c_str());
    if( testP >= end )
        break;
    // Advance & calculate the new hash value:
    testHash = ( testHash + q32 - *testP * x                 ) % q;
    testHash = ( (testHash<<5)  + *(patternlength + testP++) ) % q;
    }
return NPOS;          // Not found.

您没有使用Borland字符串库。String(大写S)是Borland字符串类。string(小写s),与std::string完全相同,是STL字符串类,这不是Borland实现(BCB5中的STL是RogueWave STL)。使用#include <cstring>可能会将std::string带入全局名称空间,这就是代码编译的原因。但你真的应该使用#include <string>std::string代替。至于NPOS,您应该使用string::npos代替,因为这是string::find()实际返回的。

#include <cstring>
#include <iostream>
int main (int argc, char *argv[])
{
   string needle = "length == eighteen";
   string haystack = "<" + needle + ">";
   if (haystack.find(needle) != string::npos)
      cout << "Found it!" << endl;
   else
      cout << "Not found" << endl;
   return 0;
}

或:

#include <string>
#include <iostream>
int main (int argc, char *argv[])
{
   std::string needle = "length == eighteen";
   std::string haystack = "<" + needle + ">";
   if (haystack.find(needle) != std::string::npos)
      std::cout << "Found it!" << std::endl;
   else
      std::cout << "Not found" << std::endl;
   return 0;
}