-1
votes

Pourquoi CalloC ne fonctionne que dans des parties spécifiques du code?

Pourquoi le premier code fonctionne bien, tandis que le second n'est pas? La seule différence est l'endroit où je place calloc dans la fonction secondaire. La raison pour laquelle je demande est que j'aurais pensé que le deuxième code est celui qui fonctionne, en considérant la valeur de divisor_number est seulement connue une fois que je fais la boucle de la fonction secondaire. Pourriez-vous me donner une explication rapide sur celui-ci? Merci!

En outre, je ne reçois aucune erreur ni avertissements lors de l'exécution du deuxième code. Y a-t-il une façon de pouvoir obtenir des informations supplémentaires du compilateur pour me mener dans la bonne direction? Merci!

NB excuses pour le code n'étant pas très organisé à partir d'un point de stand logique, il suffit de travailler pour obtenir une meilleure compréhension de quelques concepts de programmation.

1er code: xxx

2e code: xxx


6 commentaires

Les deux code sont faux, car divisor_number (transmis sur calloc ) n'est jamais initialisé. Ils ont tous deux comportement indéfini et c'est une loterie qui, le cas échéant, fonctionne comme prévu. "La valeur de divisor_number n'est connue qu'une fois que j'ai fait la boucle". divisor_number est jamais connu.


Dans la deuxième version, vous avez UB, car diviseurs ne pointe pas sur la mémoire valide dans la boucle, lorsque vous l'indexez.


calloc attribue la mémoire, vous ne pouvez pas attribuer la mémoire après Vous avez déjà essayé d'utiliser ladite mémoire. Vous devez l'allouer avant.


@ Weathervane - dans le premier segment: * diviseurs = 0 initialise le pointeur, puis diviseurs = save_number (& int_number); retourne la mémoire allouée. Où est l'UB dans le premier segment?


" Je ne reçois pas d'erreurs ni d'avertissements lors de l'exécution du deuxième code. ", regarde Valgrind pour voir les erreurs à l'exécution de Version


@ryyker dans les deux sections, fonction sauvegarde_number () définit int divisor_number qui dans un cas est immédiatement transmis à calloc et dans l'autre cas est incrémenté. Avant Ditto. Nulle part a été une valeur fixée.


4 Réponses :


-1
votes

Il suffit de partir ici le code final qui fonctionne, en tenant également compte @weathervane Commentaire, et assurez-vous que divisor_number code> est initialisé.

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>


int* save_number(int *int_number);

int main()
{
   int int_number, *divisors = 0, count_even, i;

   printf("Please enter an integer:");
   divisors = save_number(&int_number);

   for (i = 1; i <= int_number; ++i)
   {
      if (divisors[i-1] % 2 == 0 && divisors[i-1] != 0)
      {
         printf("%d\n", divisors[i-1]);
         count_even++;
      }
      continue;
   }
   printf("Total even divisors: ");
   printf("%d\n", count_even);
   return 0;
}

int* save_number(int *int_number)
{
   int i, *divisors = 0, divisor_number = 0;
   divisors = calloc(divisor_number, sizeof *divisors);

   scanf("%d", int_number);

   for (i = 1; i <= *int_number; ++i)
   {
      if (*int_number % i == 0)
      {
         divisors[i-1] = i;
         printf("%d\n", divisors[i-1]);
         divisor_number++;
      }
      continue;
   }

   return divisors;
}


1 commentaires

faire diviseurs = calloc (divisor_number, taille de * diviseurs); quand divisor_number = 0 Vous allouez un bloc de taille 0



0
votes

Dans le premier cas, lorsque vous faites

divisors[i-1] = i;


2 commentaires

divisor_number est ininitialisé dans codes . Dans la seconde a été incrémenté mais n'est pas moins défini.


Bon point, mais dans le second cas, le crash se passera même avant que divisor_number est utilisé.



0
votes

Vous avez plusieurs comportements non définis dans votre code:

faire p>

calloc (divisor_number, taille de * diviseurs); p> blockquote>

tandis que divisor_number code> n'est pas encore initialisé, puis à l'aide du bloc attribué p>

dans votre deuxième proposition alloue également le bloc après l'écriture em> en elle. p>

Si l'utilisateur ne saisit pas un entier valide, laissez * int_number code> non initialisé. p>

Si vous ne pouvez pas affecter le bloc (indépendamment de l'UB précédent) p>


Vous pouvez facilement supprimer ces UBS. p>

Vous connaissez les éléments numériques dont vous aurez besoin pour enregistrer car c'est la valeur du numéro que vous lisez

dans le premier code remplacer P>

int i, *divisors;

if ((scanf("%d", int_number) != 1) || (*int_number < 1)) {
  ..indicate error
  exit(1); 
}
if ((divisors = calloc(*int_number, sizeof *divisors)) == NULL) {
  ..indicate error
  exit(1); 
}

...


0 commentaires

0
votes

Les deux versions du code ont des erreurs.

dans la première version que vous avez: xxx

ici, divisor_number est non initialisé Sa valeur est indéterminée . Il suffit d'utiliser la valeur invoque comportement non défini . Vous avez "chanceux" que les choses fonctionnent, soit parce que cette valeur qui est arrivée à être transmise à calloc était suffisamment grande pour allouer suffisamment de mémoire, ou que ce n'était pas assez grand et que vous n'aviez pas réussi à ne pas casser quoi que ce soit en écrivant au-delà de la fin de la mémoire allouée.

dans le deuxième code: xxx

à ce point divisiors est défini Pour NULL, vous êtes donc la désérogation d'un pointeur nul qui est également un comportement indéfini. De plus, comme dans le premier code, divisor_number est encore ininitialisé, vous essayez de l'incrémenter.

Votre réponse postée ne fonctionne pas non plus car vous indiquez calloc < / Code> Pour allouer 0 octets de mémoire, tout accès à l'élément de la matrice alloué lit après la fin.

Vous devez utiliser la valeur lue dans int_number pour allouer mémoire et appelant calloc juste après le faire. C'est la quantité réelle d'espace dont vous avez besoin. xxx


2 commentaires

AVERTISSEMENT DOIT ÊTRE CALLOC (* INT_NUMBER ... Et c'est ce que je fais dans ma réponse (sur le fait que j'ai ajouté des tests pour éviter l'UB si un nombre non valide, etc.) ;-);


@bruno bonne prise. Fixé.