2011-12-19 13 views
1

EDIT:今後の読者の皆様、std :: stringは問題とは関係ありません。それは未完成の配列だった。std :: string定義を追加するとアクセス違反が発生する

一言で言えば、問題は、単一のstd :: stringの宣言をC以外のプログラムに追加すると、エラー "Access violation reading location 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; 
} 
+2

私はこのLDAPのことは知らないけど、私の疑惑は_Undefined Behavior_どこかで呼び出され、文字列の定義[(!)](http://stackoverflow.com/questions/1410563/)がそれを明らかにするだけですAVとして。 – sbi

+0

OKだから、実際にはLDAPの使い方が間違っていると思います。 (「はい」と答える必要はありません) –

+0

はい、私はそれを信じていますが、バンタールは何が間違っているかを見つけました。 – sbi

答えて

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

属性配列がNULLで終了する必要があります:このような奇妙なものはC++で観察されている場合

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

YAY !!!みんなの貴重な時間を無駄にして申し訳ありません!小切手はどこに送付しますか? :) –

+0

長さを指定して割り当てを使用するのはなぜですか?初期化により、コンパイラは長さを計算できます。 –

+0

あなたが記述するスタイルで新しい宣言を書くよりも、おそらくコードのコピー/貼り付け/修正が速かったでしょう。ちょうど推測する... –

1

私の経験によると、どのような実際に起こっていることのいくつかの作品ですコードがどこかでメモリを壊してしまい、この腐敗は、それ自体がまったく現れない可能性を含め、様々な奇妙な方法で現れることがあります。これらの兆候は、物事がメモリ内のどこにあるかによって異なるため、新しい変数を導入すると、物がメモリ内で動かされるだけで、破損が現れないようにすることができます。だから、私があなたの靴の中にいたなら、私は文字列そのものを完全に忘れてしまい、コードの残りの部分に集中して、そこで何をしてメモリを破壊するのかを正確に突き止めようとします。

私は、例外をスローするこれらの関数の仕様に含まれていないにもかかわらず、戻り値をチェックせずにいくつかの関数を呼び出すことに気付きました。したがって、これらの関数のいずれかが失敗した場合(ldap_initAで始まります)、失敗しなかったと仮定して実行すると、メモリが破損する可能性があります。あなたはこれをチェックしましたか?

+0

ありがとうマイクあなたは正しいです。私の終わりのない配列は、犯人でした。私はもともとすべての戻り値をチェックしましたが、投稿されたコードをよりコンパクトにするために取り出しました。面白いですが、std :: string DEFINITION(宣言ではない)がなければ、未終了の配列は問題ありません。実際にはC/C++をよく使う必要があります。私のような軽量ではない... –

+0

はい、そしてもちろん@Bantharは、コードを見るだけで問題が何であるかを正確に知ることができます。 (私はLDAPに慣れていないので知らなかった) –

2

私はldap_search_sAが何であるか分からないが、 OpenLDAPの中ldap_search機能はchar*のNULLポインタで終わる配列へのポインタを取ります。 渡すアレイが正しく終了していないため、何かが になることがあります。私はstd::vector<char*>、一般的には を使用し、システマティックに末尾に を後置するC++関数で呼び出しをラップすることをお勧めしますので、忘れないでください。そのような単純なケースでは:

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

トリックを行います。おそらく警告を発するだろう。

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

しかし、OpenLDAPのインターフェイスを使用すると、 が呼び出しサイトでconst_castを必要があると思いますので、constを無視するレガシーC、である:それは本当に でなければなりません。 (関数 をラップするもう1つの引数。)

最後に、難読化することを強くお勧めします。typedef のようにPCHAR;彼らはコードをあまり明確にしません。

+0

ありがとう。私はそのアドバイスを受け取ります... –

+0

FWIW:私は一般的にこの種のものを 'static'と' const'と宣言しています(しかし 'const'は後で' const_cast'を必要とします)。これは 'static char const * const attributes [] = {...};'です。あなたのコードに関しては、Cスタイルの配列の利点の1つは、配列のサイズを指定する必要がないということです。コンパイラは、初期化値から自身を計算します。 –

関連する問題