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

C++ Discussion :

Récupérer taille allouée d'un char* passé en argument d'une fonction


Sujet :

C++

  1. #1
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut Récupérer taille allouée d'un char* passé en argument d'une fonction
    Bonjour,

    Je souhaiterais récupérer la taille max ou en quelque sorte le "sizeof" d'un char* passé en argument d'une fonction (et donc sans fournir la taille en argument, juste le char*).

    Voici un exemple pour illustrer:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void f(char* str)
    {
      // ici besoin de la taille de str pour y copier une longue chaine de caractère constante
      // du genre strncpy(str, ???, constString);
    }
     
    int main()
    {
      char buf[32];
     
      f(buf);
     
      return 0;
    }
    J'ai essayé plusieurs manières en vain, je précise que je souhaite trouver une solution sans fournie la taille en argument:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void f(char* str, unsigned int size);
    Le problème c'est que je pensais pouvoir récupérer la taille par un sizeof(str) mais cela renvoie la taille d'un pointeur (4 octets).
    Je précise que "buf" est vide ou plutot non-initialisé avant d'être passé à la fonction f(), donc strlen(str) donnera zéro.

    Voilà, donc si vous avez une solution, je suis preneur.

    Merci de votre aide.

  2. #2
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Hello

    Même avec une allocation dynamique (ce qui n'est pas le cas dans ton exemple), il n'y a pas de manière standard de le faire. Même si tu trouves une astuce tordue pour le faire, je le déconseilles fortement.

    Si tes appels sont toujours similaires à ton exemple c'est à dire basé sur des tableaux de char et pas des pointeurs, un template peut te rendre service:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <iostream>
    #include <string>
     
    template <std::size_t Size> std::string char_array_to_str(char const (&arg)[Size]) {
      return std::string(arg, Size);
    }
     
    int main() {
      char roger[3] = {'a','b','c'};
      std::cout << char_array_to_str(roger) << std::endl;
    }
    Find me on github

  3. #3
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Merci pour ton aide.

    Par contre, je ne cherche pas à convertir mon char* en string, je cherche simple à recupérer sa taille pour pouvoir le remplir sans "déborder" la-dite taille.

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    Pour commencer, sizeof(n'importe quoi*) = sizeof(void*) = la taille d'un pointeur.
    A la différence d'un tableau (une variable dont le type est truc[]), dont sizeof retournera bien la taille complete.

    Tu peux tenter d'utiliser strlen(), mais cela suppose deux choses: ton pointeur n'est pas nul, ca, tu peux le controler, et le contenu est une chaine de caractères au sens du C: une suite de caractère sans '\0', suivi d'un '\0'.

    Cela dit, un pointeur général ne connais pas de taille.
    Une autre façon de procéder, c'est de passer par la différence entre deux pointeurs... mais il faut les deux pointeurs.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Le soucis est que le code C++ sera compilé sous la forme d 'une DLL, et le tableau est fourni (et alloué statiquement du genre char array[1000]) depuis du code Java (qui charde la DLL C++).

    Donc le tableau "reçu" du Java par la DLL est sans doute vide ou plutôt non-initialisé.

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 059
    Points : 12 095
    Points
    12 095
    Par défaut
    Et si c'est correctement designé, l'API doit te fournir la taille du buffer en octet.
    T'aurais pas un peu zappé la documentation de l'API JAVA ?

  7. #7
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    En fait, je vais être plus précis.

    Il s'gait d'une IHM Java qui appelle du JNI pour charger la DLL C++.

    Je m'occupe que du developpement de la DLL C++, donc je doit me comformer aux signatures de fonctions attendues (sans tailles de tableaux, en l'occurence void f(char* str)).

  8. #8
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    Donc tu ne peux pas connaitre cette taille par magie.
    Un pointeur n'est vraiment qu'une adresse.

    Par contre, tu as certainement une documentation te disant quelle taille est autorisée.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  9. #9
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Non, car comme indiquée précedemment, la chaine arrive vide ou non-initilisée et sera remplie dans la DLL C++.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    // DLL C++
    void f(char* str)
    {
      string sTemp("Portez ce vieux whisky au juge blond qui fume");
      strncpy(str, ???, sTemp);// si je mets strlen(str) à la place de ??? ça n'ira car la chaine est vide 
    }

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 059
    Points : 12 095
    Points
    12 095
    Par défaut
    On va faire dans l'efficace.

    Tu contactes ton copain le plus balèze pour qu'il t'accompagne au meeting avec les JAVAistes.

    Et tu dis gentiment à ces crétins de designer CORRECTEMENT leur API JNI ou sinon ton copain sera le bras armée de la théorie de Darwin.

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Ce que tu espères faire est strictement impossible.
    Une telle méthode doit obligatoirement savoir la taille maximale. Tu as parlé d'un char[1000] plus haut.. qu'en est-il ?

    de deux choses l'une
    - tu dois allouer str et t'en charges
    -> nécessitera sans doute l'ajout d'une fonction de libération
    - tu dois utiliser str, et il te faut la taille maximale possible

    Y'a pas de magie, et c'est pas par hasard que toutes les méthodes qui utilisent du char* prennent un paramètre supplémentaire pour connaître leur taille, ou savent la "deviner" à coup de strlen.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  12. #12
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Je voulais justement eviter d'en arriver à de telles extremités.

    Car je pensais me proposer pour faire moi-même les modifs dans JNI, mais le problème est que toutes les autres DLL existantes (dont je ne m'occupe pas) suivent l'interface définit dans le JNI, et que pour qu'elle soit toujours utilisables en Java il faudrait ensuite toutes les modifier pour qu'elle soit chargeables par le JNI (si on ne respecte pas scrupuleusement l'ensemble de fonctions définit et leurs signatures, la DLL crash).

  13. #13
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Il te reste plus qu'à rajouter la précondition suivante : la chaîne ne contient pas de '\0' sauf le dernier caractère comme le propose leternel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char buf[32];
    for (std::size_t i = 0; i < 32; ++i) { buf[i] = 'a'; }
    buf[31] = '\0';
    f(buf);
    --- --- ---

    Ou alors la taille est dans une constante / variable plus ou moins globale.

  14. #14
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Changer la signature de la fonction n'est aps possible (pour les raisons evoquées precedement), donc "f(buf, sizeof(buf));" pas possible.

    Mettre une taille en globale c'est possible, mais, comment s'assurer que la taille constante est la même que dans le code JNI, exemple:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // Code JNI
     
    #define SIZE 1000
     
    ...
     
    char str[SIZE]; // str sera fournit à la DLL C++
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // Code C++
     
    #define SIZE 1000
     
    void f(char* str)
    {
      string sTemp("Portez ce vieux whisky au juge blond qui fume");
      strncpy(str, SIZE sTemp);
    }
    Donc là OK, mais le problème risque de se corser si des modifs sont faites dans le JNI (j'ai pas la main dessus) tout en continuant d'utiliser la DLL (sans synchroniser les changements):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // JNI
    #define SIZE 500
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // C++
    #define SIZE 1000
     
    void f(char* str)
    {
      string sTemp("Portez ce vieux whisky au juge blond qui fume ......... etc"); // chaine de 800 char par exemple
      strncpy(str, SIZE sTemp);
    }
    Là on aura un soucis d'overflow!

  15. #15
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Tu peux ajouter une fonction dans la dll ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::size_t f_c_str_size() { return 32; }

  16. #16
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Je pourrais àjouter une fonction usage "interne" de la DLL, mais celle que tu me propose présume que je connaise la taille du tableau, or c'est ce que je cherche à determiner.

    Donc si tu as une fonction du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::size_t getSizeArray(char* array);// array chaine non-initilaisée et probablement vide
    mon problème serait resolu.

  17. #17
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par LinuxUser Voir le message
    Je pourrais àjouter une fonction usage "interne" de la DLL, mais celle que tu me propose présume que je connaise la taille du tableau, or c'est ce que je cherche à determiner.
    Je propose une fonction (qui pourrait juste être une variable globale constante) qui retourne une taille arbitraire et qui "force" (faut écrire ça dans la documentation) la taille du char*.

    Si tu veux que la taille du char* puissent varier, il te faut une variable globale non constante qui devra être mise à jour avant l'appel de la fonction (non thread-safe).

  18. #18
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    Ta signature est bien void f(char*)? dans ce cas, tu reçois une copie d'un pointeur de char.
    Donc tu ne peux pas allouer dans ta fonction.

    J'en déduis que tu reçois de la mémoire allouée.
    Trois choix sont possibles:
    1. Cette mémoire est dans un état utilisable: par exemple, c'est déjà une string.
    2. Cette mémoire est de taille connaissable par un moyen explicite quelconque, et la documentation dit lequel
    3. Cette mémoire est pourrie, et tu peux a peine supposer que le premier char est présent.



    Dans les deux premiers cas, tu peux avoir la taille.
    Dans le troisième, tu te contenteras d'accepter que ca ira, et tu documentes que "Comme la taille du buffer n'est pas déterminable dans cette fonction, c'est à l'utilisateur de s'assurer qu'il n'y aura pas de fuite mémoire. Toute erreur à ce sujet permettra une attaque par buffer overflow permettant l'exécution de code arbitraire."
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  19. #19
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 059
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 059
    Points : 12 095
    Points
    12 095
    Par défaut
    Bon, c'est un designe pourri, et ils ont fait avec.

    Alors, faut s'adapter.
    Il y a une information supplémentaire, peut-être non écrite, qui n'est pas dans la signature de la fonction.

    Comme il y a des crétins pour faire des Dll qui "fonctionnent" avec. Le plus fiable, c'est d'utiliser exactement les mêmes assertions que les autres ont fait.

    Ainsi, si ça plante, ça plante pour tout le monde (toutes les Dll).

  20. #20
    Membre confirmé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Points : 616
    Points
    616
    Par défaut
    Je suis bien dans le troisième cas, mais je voulais m'assurer qu'il n'y avait pas quand même une solution à laquelle je n'avais pas pensée.

    Je vous remercie tous beacuoup.

    Je vais mettre le tag "résolu" car maintenant les choses sont tout à fait claires, merci encore.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [RegEx] Récupérer les arguments d'une fonction
    Par brunoperel dans le forum Langage
    Réponses: 2
    Dernier message: 29/07/2008, 20h46
  2. Réponses: 7
    Dernier message: 22/06/2008, 01h05
  3. récupérer le nombre d'arguments d'une fonction
    Par hector2 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 17/03/2008, 12h35
  4. Réponses: 7
    Dernier message: 21/01/2008, 16h17
  5. Réponses: 4
    Dernier message: 05/10/2005, 19h19

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