Je suis tombé sur la partie de code étrange suivante.Imagine Vous avez le suivant TYPEDEF:
LPCWSTR DllFileName; //Path to the dll stored here LPCSTR _FunctionName; // (mangled) name of the function I want to test MyFunctionPointer functionPointer; HINSTANCE hInstLibrary = LoadLibrary( DllFileName ); FARPROC functionAddress = GetProcAddress( hInstLibrary, _FunctionName ); functionPointer = (MyFunctionPointer) functionAddress; //The values are arbitrary int a = 5; int b = 10; int result = 0; result = functionPointer( a, b ); //Possible error?
8 Réponses :
J'ai bien peur qu'il n'y ait aucun moyen de savoir - le programmeur est requis pour connaître le prototype au préalable lors de l'obtention du pointeur de la fonction et de l'utiliser. p>
Si vous ne connaissez pas le prototype à l'avance, je suppose que vous devez implémenter une sorte de protocole avec la DLL où vous pouvez énumérer des noms de fonction et leurs paramètres en appelant des fonctions connues dans la DLL. Bien entendu, la DLL doit être écrite pour se conformer à ce protocole. P>
Ce n'est pas mon point: je sais que je ne devrais pas appeler la fonction comme ça, mais exactement quel genre d'erreur cela va causer? Est-ce quelque chose qui peut être manipulé, ou je vais juste faire gâcher ma pile d'appel et bloquer l'application.
Tu ne peux pas gérer ça. Vous ne pouvez pas gâcher la pile si la fonction est une fonction C, mais les paramètres auront mal, ce qui peut entraîner des accidents.
En règle générale Si vous appelez LoadLibrary et GetProcByadDrees, vous avez une documentation qui vous indique le prototype. Encore plus souvent comme avec tous les Windows.dll, vous recevez un fichier d'en-tête. Bien que cela entraînera une erreur si mal est généralement très facile à observer et non au type d'erreur qui se faufiler dans la production. P>
J'ai des raisons de croire que le gars qui a écrit cela n'a pas eu d'informations sur la fonction appelée, mis à part son nom.so, dans le cas où nous voulons vraiment le mauvais nombre d'arguments, ce qui va se passer?
Tout peut arriver. Et si la fonction prend trois arguments ou une chaîne et un int? Appeler une fonction avec le mauvais numéro / type d'arguments n'est indéfini.
Je ne le pense pas, c'est une bonne question, la seule disposition est que vous devez savoir quels paramètres sont pour que le pointeur de fonction fonctionne, si vous ne faites pas et que vous ne faites pas aveuglément les paramètres et l'appelez, il sera Crash ou sauter dans les bois ne jamais être revu ... il appartient au programmeur de transmettre le message sur ce que la fonction attend et du type de paramètres, heureusement, vous pourriez le démonter et découvrir de regarder le pointeur de la pile et adresse attendue au moyen du «pointeur de pile» (SP) pour connaître le type de paramètres. p>
Utilisation de PE Explorer Par exemple, vous pouvez déterminer quelles fonctions sont utilisées et examinent la décharge de démontage ... P>
J'espère que cela aide, Meilleures salutations, Tom. P>
La plupart des compilateurs C / C ++ ont l'appelant configurant la pile avant l'appel et réajustez le pointeur de la pile par la suite. Si la fonction appelée n'utilise pas de pointeur ou d'arguments de référence, il n'y aura pas de corruption de mémoire, bien que les résultats ne valent rien. Et comme le dit Rerun, le pointeur / des erreurs de référence apparaît presque toujours avec un modicum de tests. P>
Hmm, je pensais qu'avec StdCall, il incombait à la Callee de réajuster la pile après l'appel de la fonction.Tratre, si nous transmettons le mauvais nombre de SAR arguments, ne serait-ce pas hors du SP?
Non I NORMAL C / C ++ compilateurs, l'appelant est responsable. C'est ainsi que des fonctions variadiques telles que PrintF peuvent travailler avec un degré de sécurité raisonnable.
Oui, mais encore une fois, la convention appelante par défaut pour la plupart des compilateurs C / C ++ est _CDecl, pas _stCall, autant que je sache
Il va soit planter dans le code DLL (car il a été passé de données corrompu), ou: je pense que Visual C ++ ajoute du code dans les constructions de débogage pour détecter ce type de problème. Il dira quelque chose comme: "La valeur d'ESP n'a pas été enregistrée sur un appel de fonction" et pointera au code près de l'appel. Cela aide mais n'est pas totalement robuste - je ne pense pas que cela vous empêchera de passer dans le mauvais argument de la taille d'une même taille (par exemple. Int au lieu d'un char * paramètre sur x86). Comme d'autres réponses disent, il suffit de savoir, vraiment. P>
Ce serait assez utile. Certains moyens d'avoir le problème détecté et de ne pas obtenir l'écran d'erreur? Parce que si tel est le cas, je serais en mesure de corriger le problème quelque peu. Je ne suis pas vraiment inquiet de passer des paramètres incorrects de la même taille, à condition que j'évite la corruption de pile en dehors de la fonction.
Je ne sais pas de la détecter vous-même; Ma meilleure hypothèse serait de savoir quelle est la construction de débogage et ajoutez votre propre assemblage en ligne pour effectuer la même vérification dans une version de libération. Cela semble difficile cependant.
si strong> c'est une fonction __STDCall Donc, si c'est une préoccupation majeure, vous pouvez regarder le nom brut de la fonction et vérifier que la quantité de données que vous mettez sur la pile correspond à la quantité de données qu'il va effacer la pile. p>
Notez que ce n'est toujours qu'une protection contre Murphy, pas Machiavelli. Lorsque vous créez une DLL, vous pouvez utiliser un fichier d'exportation pour modifier les noms des fonctions. Ceci est fréquemment utilisé pour éliminer le nom Mangling - mais je suis sûr que cela vous permettrait également de renommer une fonction de XXX @ 12 à XXX @ 16 (ou autre) pour tromper le lecteur sur les paramètres qu'il attend. p>
Edit: (principalement en réponse au commentaire de Msalters): Il est vrai que vous ne pouvez pas appliquer __stDCall à quelque chose comme une fonction membre, mais vous pouvez certainement l'utiliser sur des fonctions globales, qu'ils soient écrits en C ou C ++. P>
Pour des choses comme des fonctions de membre, le nom exporté de la fonction sera muté. Dans ce cas, vous pouvez utiliser @nn code> à la fin, où nn code> est un nombre. Ce nombre est le nombre d'octets que la fonction attend en tant qu'arguments et effacera la pile avant son retour. P>
UndecoratesMbolName code> pour obtenir sa signature complète. En utilisant cela est quelque peu non-trivial, mais pas complexe scandaleusement complexe non plus. P>
La question est étiquetée C ++, pas C. Mais vous décrivez le nom Mangling of c fonctions.
Il y a trois erreurs que je peux penser si le numéro attendu et utilisé ou le type de paramètres et de la convention d'appel diffèrent: P>
en deux mots: comportement non défini code> p>
Il n'y a pas de réponse générale. Les mandats standard que certaines exceptions sont lancées dans certaines circonstances, mais en dehors de cela décrit comment un programme conforme sera exécuté et dit parfois que certaines violations doivent entraîner un diagnostic. (Il peut y avoir quelque chose de plus spécifique ici ou là, mais je ne m'en souviens certainement pas un.) P>
Qu'est-ce que le code fait là-bas n'est pas en fonction de la norme, et comme il y a un casting, le compilateur a le droit d'aller de l'avant et de faire la chose stupide que le programmateur veut sans plainte. Ce serait donc une question de mise en œuvre. P>
Vous pouvez vérifier votre documentation de mise en œuvre, mais ce n'est probablement pas là non plus. Vous pouvez expérimenter ou étudier la manière dont les appels de fonction sont effectués sur votre mise en œuvre. P>
Malheureusement, la réponse est très susceptible d'être que cela va visser quelque chose sans être immédiatement évident. P>
Si vous n'êtes pas sûr des fonctions exactes exportées par une DLL (type exact, mais pas i> la convention appelante), utilisez le Walker de dépendance.