web-dev-qa-db-fra.com

Comment retourner un tableau local en C++?

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

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

Je reçois un avertissement:

avertissement C4172: adresse de retour de variable locale ou temporaire

21
user494461

Vous devez allouer dynamiquement votre tableau de caractères:

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

pour C++ et

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

pour C.

En effet, sans allocation dynamique, votre variable résidera sur la pile de la fonction et sera donc détruite à la sortie. C'est pourquoi vous recevez l'avertissement. L'allouer sur le tas empêche cela, mais vous devrez faire attention et libérer la mémoire une fois que cela sera fait avec delete[].

12
Luchian Grigore

Je suggérerais std::vector<char>:

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

Et si vous avez besoin de char* dans votre code, vous pouvez utiliser &reply[0] quand vous le souhaitez. Par exemple,

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

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

Et tu as fini. Cela signifie que si vous utilisez l'API C, vous pouvez toujours utiliser std::vector, car vous pouvez transmettre &reply[0] à l'API C (comme indiqué ci-dessus) et reply à l'API C++.

En résumé: évitez d’utiliser new autant que possible. Si vous utilisez new, vous devez le gérer vous-même et vous devez delete lorsque vous n'en avez pas besoin.

27
Nawaz

Le message d'avertissement est correct. Vous retournez l'adresse d'un tableau local qui disparaît après le retour de la fonction.

Vous pouvez le faire en utilisant une allocation de mémoire dynamique:

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

Le problème, c’est que vous devez vous assurer que vous _free() le pointeur ultérieurement pour éviter une fuite de mémoire.

Vous pouvez également passer le tampon dans la fonction.

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

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

Cela évite le besoin d'une allocation de mémoire. C'est en fait le moyen privilégié de le faire.

10
Mysticial

Le problème est que buffer habite sur la pile et sort de la portée dès que vous quittez recvmsg.

Vous pouvez allouer buffer sur le tas:

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

Notez que l’appelant est maintenant responsable de l’élimination de la mémoire allouée:

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
Shubhankar Sisodia

Vous pouvez créer le tampon de manière dynamique, mais l'appelant doit savoir le libérer.

Je pense qu'il est préférable de passer dans un tampon (en supposant que recvmsg le remplisse également)

void recvmsg(char *buffer, size_t size){

}

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

Même si l'appelant décide que la dynamique est meilleure, ils sauront qu'ils doivent le libérer, ainsi que la manière spécifique de le faire (free (), delete, delete [] ou peut-être quelque chose de spécial dans un allocateur personnalisé)

1
Lou Franco

Juste pour compléter le tableau:

Il n'est pas nécessaire d'allouer de la mémoire avec malloc. Vous pouvez également créer le tampon sur la pile, mais vous devez le créer sur un cadre de pile qui dure tant que le consommateur du tampon vit. C'était l'erreur de l'OP - lorsque l'appelé était terminé, le tampon était supprimé et l'appelant avait un pointeur invalide.

Voici ce que vous pouvez faire:

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

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

Vous avez quelques options ... La façon dont vous le faites maintenant va causer un comportement indéfini car le tableau disparaîtra de sa portée une fois que sa fonction sera revenue. Donc, une option consiste à allouer dynamiquement la mémoire ..

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

N'oubliez pas de le nettoyer avec delete this (ou gratuit si vous avez utilisé malloc). Deuxièmement, vous pouvez utiliser un paramètre ...

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

Encore une fois, il en va de même pour le nettoyage. Notez également la coche de 0 pour vous assurer que vous n'appelez pas nouveau sur un pointeur déjà attribué.

Enfin, vous pouvez utiliser un vecteur ..

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

   //do stuff with vector here

   return temp;
}
0
MGZero

que diriez-vous de passer par ref

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

lorsque vous renvoyez le tampon, puisqu’il agit en tant que pointeur sur le premier emplacement du tableau, il retournera son adresse. Et à l’endroit où vous appelez la fonction, vous pouvez créer un pointeur de caractère qui stockera la valeur de cette adresse renvoyée. Après quoi, vous pouvez déplacer votre pointeur et accéder à tous les éléments de votre tableau.

0
Nitesh Narayan Lal

Le problème est que vous renvoyez un pointeur sur un tampon alloué sur la pile. Une fois que la fonction est revenue, ce tampon n'est plus valide.

0
TJD

Vous allouez le tableau sur la pile à l'intérieur de votre fonction recvmsg. Le fait de renvoyer un pointeur dans cette mémoire peut entraîner un comportement indéfini s'il est déréférencé, car la mémoire sera nettoyée à la fermeture de la fonction.

Si vous souhaitez renvoyer un pointeur en mémoire, vous devrez l'allouer dynamiquement à l'aide de malloc.

0
Ed S.