添加std::string定义会导致访问冲突

Adding an std::string definition causes Access Violation

本文关键字:访问冲突 定义 std string 添加      更新时间:2023-10-16

EDIT:亲爱的未来的读者,std::字符串与这个问题无关。这是一个未终止数组。

简单地说,问题是在只包含C的程序中添加一个std::string的声明会导致错误"读取位置0xfffffffffffffffffffffe的访问冲突"。

在下面的代码中,如果声明std::string的行被注释掉,则程序运行到完成而不会出现错误。但是,如果该行留在程序中(未注释),则程序崩溃,并出现上述访问冲突错误。当我在VS2010调试器中打开正在运行的程序时,在调用ldap_search_sA()时发生了访问冲突。

注意声明的std::string永远不会被使用。不一定要使用它才会导致访问冲突。简单地声明它将导致访问冲突。

我怀疑这与LDAP代码无关,但我可能错了。

int main() 
{
    try {
        // Uncommenting the next line causes an Access Violation 
        // at the call to ldap_search_sA().
        // std::string s;
        LDAP* pLdapConnection = ldap_initA("eu.scor.local", LDAP_PORT);
        ULONG version = LDAP_VERSION3;
        ldap_set_option(pLdapConnection, LDAP_OPT_PROTOCOL_VERSION, (void*) &version);         
        ldap_connect(pLdapConnection, NULL);
        ldap_bind_sA(pLdapConnection, NULL, NULL, LDAP_AUTH_NTLM);
        LDAPMessage* pSearchResult;
        PCHAR pMyAttributes[2];
        pMyAttributes[0] = "cn";
        pMyAttributes[1] = "description";
        ldap_search_sA(pLdapConnection, "dc=eu,dc=scor,dc=local", LDAP_SCOPE_SUBTREE,  "objectClass=computer)", pMyAttributes, 0, &pSearchResult);    
    } catch (...) {
        printf("exceptionn");
    }
    return 0;
}
    PCHAR pMyAttributes[2];
    pMyAttributes[0] = "cn";
    pMyAttributes[1] = "description";

属性数组应该以null结尾:

    PCHAR pMyAttributes[3];
    pMyAttributes[0] = "cn";
    pMyAttributes[1] = "description";
    pMyAttributes[2] = NULL;

我不知道ldap_search_sA是什么,但ldap_search在OpenLDAP接受一个指向空指针终止的char*数组的指针。你传递的数组没有被正确终止,所以任何东西都可能发生。一般来说,我建议使用std::vector<char*>。并将调用包装在一个c++函数中,该函数系统地添加了后缀终结者,这样你就不会忘记。尽管在这些简单的情况下:

char* attributes[] = { "cn", "description", NULL };

就可以了。这可能会招致警告;确实应该是:

char const* attributes[] = { ... };

但是OpenLDAP接口是遗留的C,它忽略了const,所以您需要在呼叫现场需要一个const_cast。(另一个支持包装的理由函数。)

最后,我强烈建议您放弃混淆typedef s如PCHAR;

根据我的经验,当在c++中观察到这样奇怪的事情时,实际上发生的是某些代码片段在某个地方破坏了内存,并且这种破坏可能以各种奇怪的方式表现出来,包括它可能根本不表现出来。这些表现取决于事物在内存中的位置,因此引入一个新变量可能会导致事物在内存中移动到刚好足够的位置,从而导致显示损坏,否则就不会显示损坏。所以,如果我处在你的位置,我会完全忘记字符串本身,而把注意力集中在剩下的代码上,试图弄清楚你在那里做了什么,是什么破坏了内存。

我注意到你调用了几个函数而没有检查它们的返回值,即使在这些函数的规范中没有抛出异常。因此,如果这些函数中的任何一个失败(从ldap_initA开始),而您继续假设它没有失败,那么可能会出现内存损坏。你检查过这个了吗?