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

时间:2011-12-19 10:09:07

标签: c++ visual-studio-2010 access-violation

编辑:亲爱的未来读者,std :: string与此问题无关。这是一个未终止的阵列。

简而言之,问题是将单个std :: string的声明添加到另外只包含C的程序会导致错误“访问冲突读取位置0xfffffffffffffffe。”

在下面的代码中,如果声明了std :: string的行被注释掉,程序将运行完成而不会出错。如果该行保留在程序中(未注释),则程序会因上述Acess Violation错误而崩溃。当我在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("exception\n");
    }
    return 0;
}

3 个答案:

答案 0 :(得分:4)

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

属性数组应该以NULL结尾:

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

答案 1 :(得分:2)

我不知道ldap_search_sA是什么,而是ldap_search函数 OpenLDAP获取指向空指针终止数组char*的指针。 您传递的数组没有正确终止,所以任何事情都可能 发生。一般情况下,我建议使用std::vector<char*> 并将调用包装在一个系统地后缀的C ++函数中 终结者,所以你不要忘记。虽然在这么简单的情况下:

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

会做到这一点。它可能会引发警告;它确实应该 是:

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

但OpenLDAP接口是遗留C,忽略了const,所以你就是 在呼叫站点需要const_cast。 (包装的另一个论点 功能。)

最后,我强烈建议你放弃混淆typedefPCHAR;他们只是让代码不那么清晰。

答案 2 :(得分:1)

根据我的经验,当在C ++中观察到类似这样的奇怪事情时,事实上发生的事情是某些代码在某处破坏了内存,而这种腐败可能以各种奇怪的方式表现出来,包括它可能出现的可能性。根本没有表现出来。这些表现形式取决于事物在内存中的位置,因此引入新变量可能会导致事物在内存中移动得足够多,从而导致腐败的表现,否则就不会表现出来。所以,如果我在你的鞋子里,我会完全忘记字符串本身,我将专注于其余代码,试图弄清楚你在那里做了什么会破坏记忆。

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