0
votes

Copier une chaîne - Comment dois-je faire face aux fuites de mémoire et aux cas d'erreur?

J'essaie de mettre en œuvre la fonction int * cpy_array (int V [], la taille int *) code>, qui copie la matrice dans une autre et renvoie le nouveau tableau en tant que pointeur. Je dois également faire attention aux cas d'erreur et utiliser la mémoire dynamique.

OK, je sais que Malloc retourne 0 quand il y a une nout suffisamment de mémoire disponible. Je me demandais s'il y avait des erreurs d'autres erreurs éventuelles que j'ai raté. Ensuite, je dois mettre en œuvre gratuitement () dans le cas de Succursess ainsi que dans l'affaire Error. J'ai essayé de mettre en œuvre quelque chose comme: p> xxx pré>

mais il y avait toujours une erreur avec ceci. P>

int *cpy_array(int v[], int size);

int main(void)
{
int size; 
size = 4;
int myArray[4] = {1234};
if (*cpy_array(myArray, size) == 0)
{
    printf("No memory available.");
}else{
printf("The new Array: %i", *cpy_array(myArray, size)); 
}

return 0;
}

 int *cpy_array(int v[], int size)
{
    int i;
    int *a  = malloc(size * sizeof(int));
    if(*a == 0)
    return 0;
    for (i = 0; i < size; i++)
    { 
        a[i] = v[i];
    }
return a;
}


1 commentaires

int myarray [4] = {1234}; -> int myarray [4] = {1,2,3,4}; et si (* A == 0) -> si (a == null)


3 Réponses :


0
votes

Pour détecter vos problèmes concernant la mémoire Utilisez Valgrind , si je le fais cela donne: xxx

Le saut conditionnel "dépend de la valeur ininitialisée. (s) " vient du * A dans si (* A == 0) et " lecture invalide de taille 4 ... " parce que vous déréférence 0 à cause du retour 0;


après la modification de si (* a == 0) à < code> si (a == 0) pour résoudre les deux problèmes précédents que la condition est (a priori) false et _valgrind dit: xxx

donc oui vous avez donc oui vous avez Des fuites de mémoire parce que vous avez perdu 2 fois le retour d'allocation par cpy_array

Vous devez avoir quelque chose comme: xxx

faisant ça Correction Valgrind signale rien: xxx

Je vous encourage à

  • Compilez avec toute la détection d'avertissement, comme gcc -g -wall -pedantic ...
  • Lorsque vous avez un problème, utilisez Valgrind et / ou débogueur
  • Même vous ne voyez pas de problème d'exécution de toute façon sous Valgrind , alors les problèmes peuvent être cachés

10 commentaires

Je n'ai jamais travaillé avec quelque chose comme ça ... Comment utiliser cela de manière suffisante?


supposant que le programme soit a.out plutôt que de le démarrer dans une coquille ./.out juste faire valgrind -leak-check = complet ./ A.out . Bien sûr, Nistall Valgrind avant :-)


@Francisdake j'ai édité ma réponse pour donner plus de détails


Valgrind est un outil utile, mais une surkill complète ici.


@Germannerd Que voulez-vous dire? Il est inutile de voir les erreurs? Si le O.P. Besoin d'aide, cela signifie qu'il ne voit pas ce qui est annexé. Pour lui montrer l'avantage de Valgrind est beaucoup plus que pour simplement signaler où les erreurs sont dans le code, car il sera capable de réutiliser Valgrind dans le futur, non?


@Francisdake j'ai oublié de dire que j'ai corrigé l'initialisation d'être int myarray [4] = {1,2,3,4};


@bruno Il me semble que l'OP est presque désemparé sur le langage C et peut-être la programmation en général, à en juger par le code qu'il a affiché. Et je ne pense pas que les pages de problèmes rapportées par Valgrind puissent l'aider dans la moindre idée d'acquérir les connaissances fondamentales pour comprendre le langage C et ne pas parler des concepts qu'il représente. Bien sûr, à un moment donné, il est utile d'apprendre à utiliser Valgrind - après une connaissance suffisante pour donner un sens à ce que Valgrind rapporte. Mais ce n'est que mon opinion.


Je dois admettre que c'est un peu difficile pour moi de comprendre toutes les lignes que vous avez postées. Il me semble qu'il me montre ce qui se passe en souvenir dans la mémoire avec chaque commandement, mais je ne reçois pas toutes les lignes bien que vos corrections soient plus logiques pour moi maintenant après avoir lu des réponses et peu plus encore sur Internet.


Par exemple, ce qui est perdu dans la perte?


Dans votre version CPY_ARRAY alloue la mémoire dans le tas ( MALLOC ) et le renvoie, dans Main avec cette valeur que vous venez d'accéder au premier élément ( * cpy_array (myarray, taille) ) A rien de plus, la mémoire allouée n'est plus disponible et vous ne le libérez pas, cette mémoire est définitivement perdue, c'est une fuite de mémoire je>. Comme vous pouvez le constater dans ma version, je sauve le pointeur, l'accès au premier élément comme vous l'avez fait alors je le libérez, il n'y a pas de fuite de mémoire.



0
votes

Ce n'est pas le moyen correct d'initialiser la matrice xxx pré>

écrire p> xxx pré>

ou simplement p> xxx PRE>


appeler la fonction cpy_array .. Lorsque vous écrivez P>

if ( a == NULL)


2 commentaires

Ok bien merci! Je ne comprends pas comment vous voulez dire exactement que je serais la déséroférance du pointeur avec == parce que je pensais que cela ne vérifie que la condition si le retour est égal à NULL


Si vous avez un pointeur p * p vous êtes essayer d'accéder à la mémoire qui n'existe pas ce qui est un comportement indéfini. Votre fonction CPY_ARRAY pourrait renvoyer NULL (0) si cela ne peut pas être attribué de mémoire.



1
votes

Dans votre premier extrait de code, vous avez incorrectement distribué le tableau des entiers w. Vous ne pouvez pas vous libérer des entiers simples dans ce tableau, mais ce que vous devez faire est simplement de taper:

libre (w); code> p>

qui libérera toute la matrice . Vous pouvez également voir du texte de l'erreur - Remarque: attendu 'VOID *' mais l'argument est de type 'int' "vide __cdecl libre (vide * _Memory), que le programme attendait un pointeur sur le tableau et non un entier. p>

Vous ne pouvez pas libérer l'ancien tableau, car il est créé statiquement et la mémoire est allouée au début du programme et il sera libéré à la fin de la fonction dans laquelle il a été défini par le Programme lui-même, de sorte que vous n'avez pas besoin de vous inquiéter de cela. Alors que c'est votre travail de libérer les tableaux de création de dynamisme tels que celui que vous avez créé via le CPY_ARRAY (int V [], la taille de l'int. Fonction) code> . P>

plus sur la différence entre une allocation statique et dynamique, vous pouvez rechercher ici: p>

Différence entre l'allocation statique de la mémoire et la répartition de la mémoire dynamique P>

Cette partie du code, n'imprimerait pas la matrimonie ( tu vas juste pri NT le premier numéro de tableau), et aussi vous appelez la fonction deux fois, ce qui est excessive et ne doit être effectué qu'une seule fois pour le même tableau. P>

 if(a == NULL)


5 commentaires

Bien merci! Quelque chose qui me puzzle un peu ici est que je retourne le pointeur et je dois les libérer avant de retourner? Cela n'a aucun sens pour moi parce que je ne reviendrais rien. Je pense que je mélange quelque chose ici dans le mauvais sens ...


Eh bien, si vous libérez avant de retourner de la fonction, vous ne retournerez jamais le tableau dynamique copié et vous avez raison, cela n'a pas de sens. Le nouveau tableau de copie doit être libéré après son travail et n'est plus utilisé. Cela a plus de sens pour moi.


Donc, je devrais le libérer dans la principale après son utilisation et non dans la fonction séparée avant de retourner?


Ouais tu devrais. Libérez-le avant d'utiliser cela n'a aucun sens. Et aussi vérifier la réponse principale, j'ai ajouté une dernière chose. Si vous avez plus de questions, n'hésitez pas à demander.


Merci, j'ai oublié le pour-Printf dans le tout et je me demandais simplement pourquoi cela ne fonctionne pas: D Merci! :)