web-dev-qa-db-ja.com

C ++でローカル配列を返す方法は?

char *recvmsg(){
    char buffer[1024];
    return buffer;
}

int main(){
    char *reply = recvmsg();
    .....
}

警告が表示されます:

警告C4172:ローカル変数または一時アドレスを返します

22
user494461

文字配列を動的に割り当てる必要があります。

char *recvmsg(){
   char* buffer = new char[1024];
   return buffer;
}

c ++および

char *recvmsg(){
   char* buffer = malloc(1024);
   return buffer;
}

c用.

何が起こるかというと、動的割り当てを行わないと、変数は関数のスタックに常駐するため、終了時に破棄されます。そのため、警告が表示されます。ヒープに割り当てるとこれを防ぐことができますが、delete[]を使用して一度行ったメモリを慎重に解放する必要があります。

13
Luchian Grigore

std::vector<char>をお勧めします:

std::vector<char> recvmsg()
{
    std::vector<char> buffer(1024);
    //..
    return buffer;
}
int main()
{
    std::vector<char> reply = recvmsg();
}

そして、コードにchar*が必要になったら、いつでも&reply[0]を使用できます。例えば、

void f(const char* data, size_t size) {}

f(&reply[0], reply.size());

これで完了です。つまり、C APIを使用している場合、std::vectorをC APIに(上記のとおり)、replyをC++に渡すことができるので、&reply[0]を引き続き使用できます。 API。

要するに、newの使用はできるだけ避けてください。 newを使用する場合は、自分で管理する必要があり、不要な場合はdeleteにする必要があります。

27
Nawaz

警告メッセージは正しいです。関数が戻ると消えるローカル配列のアドレスを返しています。

これは、動的メモリ割り当てを使用して実行できます。

_char *recvmsg(){
    char *buffer = (char*)malloc(1024);
    return buffer;
}
_

問題は、メモリリークを回避するために、後でfree()ポインタを確認する必要があることです。

または、バッファを関数に渡すことができます。

_void recvmsg(char *buffer,int buffer_size){
    //  write to buffer
}

void main(){
    char buffer[1024];
    recvmsg(buffer,1024);
}
_

これにより、メモリの割り当てが不要になります。これは実際に推奨される方法です。

10
Mysticial

問題は、bufferがスタック上に存在し、recvmsgを終了するとすぐに範囲外になることです。

ヒープにbufferを割り当てることができます。

char *recvmsg(){
  char *buffer = malloc(1024);
  return buffer;
}

割り当てられたメモリを破棄するのは呼び出し側の責任であることに注意してください。

void main(){
  char *reply = recvmsg();
  free(reply);
}
6
NPE
char *recvmsg(){
    char *buffer = new char;
    cout<<"\nENTER NAME : ";
    cin>> buffer;
    return buffer;
}

int main(){
    char *reply = recvmsg();
    cout<<reply;
}
1

バッファを動的に作成できますが、呼び出し元はバッファを解放する必要があります。

バッファーを渡す方が良いと思います(recvmsgも埋めると仮定します)

void recvmsg(char *buffer, size_t size){

}

void main(){
    char buffer[1024];
    recvmsg(buffer, sizeof(buffer));
}

呼び出し側が動的の方が優れていると判断した場合でも、それを解放する必要があること、およびそれを行う特定の方法(free()、delete、delete []、またはカスタムアロケーターからの特別な方法)

1
Lou Franco

写真を完成させるために:

Mallocでメモリを割り当てる必要はありません。スタック上にバッファを作成することもできますが、バッファのコンシューマが存続する限り存続するスタックフレーム上にバッファを作成する必要があります。これはOPのエラーです。呼び出し先が終了すると、バッファーが削除され、呼び出し元が無効なポインターを取得しました。

あなたができることはこれです:

void recvmsg(char *buffer, size_t size) {
   ... do what you want ...
}

void main(void) {
    char buffer[1024];
    recvmsg(buffer, sizeof(buffer));
}
1
Juergen

いくつかのオプションがあります...これを行う方法は、hte関数が返されると配列がスコープから外れるため、未定義の動作を引き起こします。したがって、1つのオプションはメモリを動的に割り当てることです。

char * recmsg()
{ 
   char * array = new char[128];
   return array;
}

この方法で削除してクリーンアップすることを忘れないでください(またはmallocを使用した場合は解放してください)。第二に、パラメータを使用できます...

void recmsg(char * message, int size)
{
   if (message == 0)
      message = new char[size];
}

繰り返しになりますが、ここでも前と同じことをクリーンアップします。また、0のチェックに注意して、既に割り当てられているポインターでnewを呼び出さないようにしてください。

最後に、ベクトルを使用できます。

std::vector<char> recmsg()
{
   std::vector<char> temp;

   //do stuff with vector here

   return temp;
}
0
MGZero

参照渡し

char buf[1024];
PutStuffInBuff(&buf);
0
karl

バッファを返すときは、配列の最初の場所へのポインタとして機能するため、アドレスを返します。関数を呼び出す場所では、この返されたアドレス値を格納する文字ポインタを作成できますその後、ポインタを移動して、配列のすべての要素にアクセスできます。

0

問題は、スタックに割り当てられたバッファへのポインタを返すことです。関数が戻ると、そのバッファは無効になります。

0
TJD

recvmsg関数内のスタックに配列を割り当てています。そのメモリへのポインタを返すと、関数の終了時にメモリがクリーンアップされるため、間接参照される場合、ある時点で未定義の動作が発生します。

メモリへのポインタを返したい場合は、mallocを使用して動的に割り当てる必要があります。

0
Ed S.