私はCプログラマーではないので、C-stringにはそれほど精通していませんが、Cライブラリーを使用する必要があるので、問題を示すためにコードの短縮バージョンを以下に示します。
char** ReadLineImpl::my_completion () {
char* matches[1];
matches[0] = "add";
return matches;
}
私は警告を受けています:
警告-ローカル変数「matches」に関連付けられたスタックメモリのアドレスが返されました
そして、私のアプリケーションは適切に動作していないようです(この警告のせいかもしれません)。
警告とは何ですか、それは問題を引き起こしますか?
変数char* matches[1];
はスタックで宣言されており、現在のブロックがスコープから外れると自動的に解放されます。
これは、matches
を返すと、matches
用に予約されたメモリが解放され、ポインターが望ましくないものを指すようになることを意味します。
これは多くの方法で解決できますが、そのうちのいくつかは次のとおりです。
matches[1]
をstatic
として宣言:static char* matches[1];
-これはヒープ上のmatches
にスペースを割り当てます(これを不適切に使用すると、my_completion
関数のすべてのインスタンスが同じmatches
変数を共有するため、噛み付く可能性があります)。
呼び出し元の関数にスペースを割り当て、my_completion
関数に渡します:my_completion(matches)
:
char* matches[1];
matches = my_completion(matches);
// ...
char** ReadLineImpl::my_completion (char** matches) {
matches[0] = "add";
return matches;
}
ヒープ上の呼び出された関数にスペースを割り当て(malloc
、calloc
、および友人を使用)、所有者を呼び出し元関数に渡します。呼び出し元関数は、不要になったときにこのスペースの割り当てを解除する必要があります(free
)。
matches
配列を返すとき、返されるのは最初の要素のアドレスです。これは、my_completion
内のスタックに保存されます。 my_completion
から戻ると、そのメモリは再利用され、最終的に(おそらく)matches
に格納されている値を上書きして再利用されます。動作します-今でない場合は、おそらく他の問題を修正したか、少し変更したか、何か他のものになります。これは安全に無視できる小さな警告ではないためです。
これはいくつかの異なる方法で修正できます。最も明白なのは、代わりにstd::vector<char *>
[またはそれ以上のstd::vector<std::string>
]を使用することです:
std::vector<std::string> ReadLineImpl::my_completion ()
{
std::vector<std::string> strings;
strings.Push_back("add");
return strings;
}
編集:したがって、ライブラリが readline
インターフェイスに従ってchar **
を必要とする場合、これを使用します。
char** ReadLineImpl::my_completion ()
{
char **matches = static_cast<char **>malloc(1 * sizeof(char *));
matches[1] = "add";
return matches;
}
問題が解決しました!
変化する
char* matches[1];
に
char *matches = new matches[1];
次を使用して、ヒープ内のメモリをこの場合に割り当てることをお勧めします。
int* someDataForParams(void *_params) {
...
int* charCounts = calloc(96, sizeof(char*));
...
return charCounts;
}
96は単なる文字列の長さです(魔法の数)