IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Caml Discussion :

erreur dans l'éxécution d'un programme


Sujet :

Caml

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2008
    Messages
    28
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2008
    Messages : 28
    Points : 16
    Points
    16
    Par défaut erreur dans l'éxécution d'un programme
    Bonjour à tous, j'ai un petit problème lors de l'éxécution d'un programme ocaml : j'ai récupérer un bout de code d'un ami me permettant de récupérer le code hexadécimal d'une image, je l'ai compilé, et j'ai un exécutable. Le programme fonctionne parfaitement, mais à partir d'une certaine taille d'image le programme plante, en fait il s'arrête prématurément, et je ne récupère même pas un centième du code de l'image.

    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    let hexa_from_int i = match i with
      |n when 10>n -> string_of_int n
      |10 -> "A"
      |11 -> "B"
      |12 -> "C"
      |13 -> "D"
      |14 -> "E"
      |15 -> "F"
    ;;
     
    let int_from_bin i = 
      (i/16, i mod 16)
    ;;
    let hexa_from_bin i =
      let (a,b) = int_from_bin i in
        hexa_from_int a ^hexa_from_int b;;
     
     
     
    let tes = open_in Sys.argv.(1) ;;
     
    (*let rec string_from_channel chan = 
    try
    match chan with
      |chan -> hexa_from_bin (input_byte chan)^(string_from_channel chan)
    with end_of_file -> "";;*)
     
    let string_from_channel chan =
      let str = ref "" in
      let boucle =
    try
        while true do
         str :=  (!str)^hexa_from_bin (input_byte chan)
        done;
    with end_of_file -> () in
    boucle;
    !str;;
     
    let test = string_from_channel tes;;
    let out = open_out "sortie.txt" ;;
    output_string out test;;
    close_out out;;
    Pourriez vous m'indiquer pourquoi l'exécution stope ? Je me suis un peu renseigné, et c'est peut-être du à du "hard return", mais je n'ai pas trop compris à quoi cela correspondait. merci beaucoup !

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 128
    Points : 146
    Points
    146
    Par défaut
    Bon, déjà vous pouvez utiliser la commande 'xxd -ps mon_fichier > sortie.txt' pour faire la même chose.

    Vous utilisez comme convention de nommage pour la conversion des éléments "foo_from_bar", en OCaml il est plus courant d'utiliser "foo_of_bar". La lib standard utilise cette convention, donc adopter la même donnera quelque chose de plus homogène.

    "hexa_from_bin" je l'aurais plutôt nommée "hexa_of_byte" puisque en entrée cette fonction reçoit le retours de l'expression (input_byte chan) donc on a un "byte".

    "hexa_from_int" je l'aurais plutôt nommé "hexa_of_nibble" ou en abrégé "hexa_of_nib" vu qu'elle reçoit un demi-octet donc un "nibble" en anglais.

    le pattern-matching de cette fonction n'est pas exhaustif, si elle reçoit 16 comme valeur d'entrée on aura une exception "Match_failure" et à la compilation on aura un warning. C'est une bonne habitude à prendre que de ne pas ignorer ces warnings. Ici on peut par exemple utiliser la fonction "invalid_arg" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    let hexa_of_nib = function
      | n when n < 10 -> string_of_int n
      | 10 -> "A"
      | 11 -> "B"
      | 12 -> "C"
      | 13 -> "D"
      | 14 -> "E"
      | 15 -> "F"
      | _ -> invalid_arg "hexa_of_nib"
    on peut aussi simplifier le code en utilisant la construction avec "function".

    "int_from_bin" nommage pas très heureux encore une fois, déjà on ne retourne pas 1 int mais 2, et le "bin" est mal approprié aussi comme je l'ai déjà expliqué plus haut. On pourait trouver plusieur nom appropriés, mais je verrais bien "div_rem" puisqu'il s'agit d'une division où on renvoie le reste avec (remainder en anglais).

    "hexa_from_bin" idem plutôt "hexa_of_byte", cette fonction peut être réécrite plus simplement ainsi :
    let hexa_of_byte = Printf.sprintf "%X" ;;
    (vous devriez prendre le temps de lire la doc)

    "string_from_channel" idem plutôt "string_of_channel", dans cette fonction vous utilisez la concaténation à chaque nouveau caractère lu, ce qui est très inefficace. Même si vous ne cherchez pas l'efficacité ici, lire un fichier est une tâche plus que courante, vous aurez donc à réutiliser souvent la même fonction. Vous trouverez plusieurs méthodes valides ici :
    http://ocaml.tuxfamily.org/Lire_un_fichier

    Dans cette fonction vous matchez également une exception avec "with end_of_file" or cette construction est trompeuse car comme la première lettre est une minuscule vous pouvez potentiellement matcher une autre exception que "End_of_file" or la variable qui va la recevoir porte le même nom mais décapitalisé, ce qui n'est pas une très bonne chose.

    La construction "let boucle = ... in boucle;" est également à revoir. Le nom laisserait penser à une boucle, or ce n'en est pas une, puisqu'il s'agit d'une variable, et une variable inutile puisqu'elle a comme valeur unit. Et puis "boucle" c'est du français, en anglais c'est "loop".

    L'indentation de cette fonction est également à revoir (plusieurs lignes dans cette fonction ne sont même pas indentées du tout).

    Aussi "string_of_channel" est trompeur, souvent une telle fonction renvoie une chaîne correspondant au fichier, mais ici il y a une conversion en hexa, donc un nom comme "hexa_of_channel" éviterait d'induire en erreur le lecteur qui pourrait se fier au nom de la fonction sans en lire le détail.

    ensuite toute cette portion :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    let tes = open_in Sys.argv.(1) ;;
    let test = string_from_channel tes;;
    let out = open_out "sortie.txt" ;;
    output_string out test;;
    close_out out;;
    c'est pas forcément faux mais ça fait très script, perso je préfèrerais voir :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    let () =
      let filename = Sys.argv.(1) in
      let chan = open_in filename in
      let content = hexa_of_channel chan in
      let out = open_out "sortie.txt" in
      output_string out content;
      close_out out;
    ;;
    avec un point d'entrée (la partie "let () =") il est plus facile de lire où commence le script (comme main() en C), et les éléments qu'il contient sont plus facilement mis en relation avec les in qui les relient.

    Bon aussi tu nous dis que ce script fonctionne parfois et parfois pas.
    Tu es gentil mais il faudrait peut-être nous donner les éléments correspondant au cas où il ne fonctionne pas, pour nous permettre de reproduire l'erreur !
    Car là même si le code n'est pas terrible et est très lent je ne parviens pas à trouver un cas où il ne fonctionnerait pas. Si tu as un fichier d'exemple avec lequel l'erreur se produit fournit nous ce fichier, ou tu nous parle d'une taille critique "à partir d'une certaine taille" déjà il y a deux interprétations possibles, est-ce au dessus d'une taille critique ou en dessous que le prog plante ? et aussi quelle taille précisément ?

    Pour finir ton script peut être réécrit en 6 lignes de code (les 2 dernières sont optionnelles et peuvent être remplacées par "()") :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    let () =
      let ic = open_in Sys.argv.(1) in
      let oc = open_out "my_exa.txt" in
      try
        while true do
          Printf.fprintf oc "%X" (input_byte ic)
        done
      with End_of_file ->
        close_in ic;
        close_out oc;

Discussions similaires

  1. Réponses: 5
    Dernier message: 10/06/2009, 19h47
  2. Réponses: 1
    Dernier message: 27/04/2009, 18h06
  3. une erreur dans l'exécution d'un programme
    Par viou25 dans le forum Langage
    Réponses: 4
    Dernier message: 15/11/2008, 22h52
  4. Erreur Windows ! Dans l'execution d'un programme !
    Par Geoff! dans le forum OpenGL
    Réponses: 3
    Dernier message: 01/06/2006, 16h36
  5. [Lien]erreur dans mon programme python
    Par durnambule dans le forum Général Python
    Réponses: 11
    Dernier message: 29/01/2004, 14h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo