web-dev-qa-db-ja.com

C文字列を使用:「ローカル変数に関連付けられたスタックメモリのアドレスが返されました」

私はCプログラマーではないので、C-stringにはそれほど精通していませんが、Cライブラリーを使用する必要があるので、問題を示すためにコードの短縮バージョンを以下に示します。

char** ReadLineImpl::my_completion () {

    char* matches[1];


    matches[0] = "add";

    return matches;

}

私は警告を受けています:

警告-ローカル変数「matches」に関連付けられたスタックメモリのアドレスが返されました

そして、私のアプリケーションは適切に動作していないようです(この警告のせいかもしれません)。

警告とは何ですか、それは問題を引き起こしますか?

22
khajvah

変数char* matches[1];はスタックで宣言されており、現在のブロックがスコープから外れると自動的に解放されます。

これは、matchesを返すと、matches用に予約されたメモリが解放され、ポインターが望ましくないものを指すようになることを意味します。

これは多くの方法で解決できますが、そのうちのいくつかは次のとおりです。

  1. matches[1]staticとして宣言:static char* matches[1];-これはヒープ上のmatchesにスペースを割り当てます(これを不適切に使用すると、my_completion関数のすべてのインスタンスが同じmatches変数を共有するため、噛み付く可能性があります)。

  2. 呼び出し元の関数にスペースを割り当て、my_completion関数に渡します:my_completion(matches)

    char* matches[1];
    matches = my_completion(matches);
    
    // ...
    
    char** ReadLineImpl::my_completion (char** matches) {
         matches[0] = "add";
    
         return matches;
    }
    
  3. ヒープ上の呼び出された関数にスペースを割り当て(malloccalloc、および友人を使用)、所有者を呼び出し元関数に渡します。呼び出し元関数は、不要になったときにこのスペースの割り当てを解除する必要があります(free)。

34
Nemanja Boric

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;
}

問題が解決しました!

8
Mats Petersson

変化する

char* matches[1];

char *matches = new matches[1];
0
Shammel Lee

スタックの代わりにヒープを使用する

次を使用して、ヒープ内のメモリをこの場合に割り当てることをお勧めします。

int* someDataForParams(void *_params) {

    ...
    int* charCounts = calloc(96, sizeof(char*));
    ...

    return charCounts;
}

96は単なる文字列の長さです(魔法の数)

0
Mike Glukhov