7
votes

Est-il sécuritaire de passer des paramètres de chaîne Delphi const à travers les limites de Memory Manager?

subj. J'aimerais utiliser des chaînes au lieu de Pchar, car cela me dépare beaucoup de casting, mais si je fais juste xxx pré>

puis mettez-le dans un autre projet avec un gestionnaire de mémoire non partagé: P>

procedure SomeExternalProc(s: Pchar); forward;
procedure LocalProc;
var local_s: string;
begin
  SomeExternalProc(local_s); //<<--- incompatible types: 'string' and 'PAnsiChar'
end;


4 commentaires

Pourquoi ne voulez-vous pas utiliser un mm partagé? Tant que vous utilisez le type de chaîne, vous êtes lié à Delphi, il ne peut pas être une DLL générique utilisable d'autres langues. Pourquoi éviter de partager le mm?


Le type de chaîne est assez compatible, il peut être interprété par d'autres langues en tant que PCHAR. Je ne parle pas de Strings de retour, bien sûr, des paramètres de chaîne.


Ne vous laissez pas berner par le fait que les cordes ont une partie posée comme un tableau ASCIIZ (ou Pchak). Ils ont également des données avant la chaîne, et Delphi peut "toucher" ces données aussi. Passez un tableau ASCIIZ / Pchare prétendant une chaîne, et vous risquez que des données en mémoire juste avant de ne pas modifier le code DELPHI en pensant que c'est une chaîne et présente ainsi des données.


Merci, je le sais. Il n'est pas sûr de transmettre Pchaler en tant que chaîne (mise de côté la conversion automatique de Delphi), mais elle est toujours sûre de transmettre la chaîne comme Pchar.


4 Réponses :


13
votes

Cela fonctionnerait probablement, tant que vous n'utilisez jamais votre DLL uniquement à partir du code compilé dans la même version de Delphi. Le format interne de chaîne a été connu pour changer entre les versions, et vous n'avez aucune garantie formelle qu'elle ne changera plus.

Si vous voulez éviter de devoir jeter partout où vous l'utilisez, Essayez d'envelopper la fonction, comme ceci: xxx

puis dans votre code, vous appelez myExternalProc au lieu de someexternalProc , et tout le monde est heureux.


5 commentaires

Heh, me bat de moins d'une minute :)


Je fais cela depuis un certain temps, mais écrit tous ces stubs ... ( Edit: Code généré par chèque pour la version en ligne, sans addréfs après tout )


Oh, et ce n'est pas toujours possible, prenez des interfaces par exemple - vous ne pouvez pas les prolonger.


@HIMELFH: Bon point. Dommage que vous ne puissiez pas déclarer une aide d'interface, comme vous le pouvez pour les classes et les enregistrements. Ils seraient vraiment utiles pour ce scénario.


Trouvé une solution, juste maintenant: déclarez deux interfaces avec le même guid et les mêmes déclarations: une avec "Const String", l'autre "Pchar". Implémentez celui avec pCHAR, accéder à celui avec des cordes. Sale hack, mais mieux que rien.



6
votes

Si l'application et la DLL sont écrites dans la même version DELPHI, utilisez simplement un gestionnaire de mémoire partagé (plus de détails ici ).

Si un côté est écrit dans une langue différente de celle qu'il n'y a pas d'autre moyen, mais d'utiliser Pchaler ou WEWString (les withestrings sont gérés par le comité de mémoire COM).

ou vous pouvez écrire une fonction d'emballage: xxx


0 commentaires

-1
votes

Je recommande d'utiliser un gestionnaire de mémoire alternatif tel que RECYCLERMMM ou FASTMM. Ils ne nécessitent aucune dll partagé partagée et vous permettent de passer des chaînes aux DLL en toute sécurité. En tant que bonus, vous pouvez obtenir une bonne amélioration de la performance dans toute l'application.

FastMM est utilisé comme gestionnaire de mémoire par défaut dans Delphi 2006 et supérieur. En outre, c'est un bon outil pour rechercher les fuites de mémoire.


6 commentaires

Merci, bien que je sache tout ça. Je n'utilise pas, ni plus précisément, pas s'appuyer sur le mm partagé parce que je veux une interopérabilité, et je pense aussi à compter sur la mm partagée, c'est un style mauvais - vous fait oublier la bonne gestion de la mémoire.


-1. Ce n'est pas vrai. FastMM vous oblige à partager le gestionnaire de mémoire afin de passer des chaînes en toute sécurité. Il est livré avec une unité appelée SimpleShareMem pour y accomplir. Il n'y a tout simplement aucun moyen de partager la gestion des chaînes en toute sécurité sans que les deux sources utilisent le même tas.


Mason, où ai-je dit quelque chose comme ça? J'écris à propos de la DLL externe (Borlandmm.dll). Oui, SimpleSharemem est nécessaire si vous souhaitez partager la mémoire entre application qui n'utilisent pas FastMM et des bibliothèques utilisent FastMM. Mais je parlais d'utiliser FastMM dans l'application et la DLL.


Même lorsque vous utilisez FastMM pour l'application et la DLL, si vous ne mettez pas SimpleShaRemem dans, l'application et la DLL se retrouveront avec leurs propres tas au lieu de partager. Il est vrai qu'il ne nécessite pas de DLL partagé partagée externe, mais vous devez toujours configurer explicitement la mémoire partagée au sein de l'EXE et de la DLL ou de ne fonctionnera pas.


Afaik Le Full Fastmm est capable de partager le mm sans SimpleShaeMemem - permet simplement de définir les définitions appropriées dans le fichier .inc.


Vrai. Voici la citation de la FAQ Fastmm: Q: Comment puis-je obtenir ma DLL et ma demande principale pour partager FastMM afin que je puisse transmettre de longues chaînes et matrices dynamiques entre eux? R: Le moyen le plus simple consiste à définir ShareMM, ShareMIMiflibrary et TentativeSeduedmm dans FASTMM4.PAS et ajouter FASTMM4.PAS en haut de la section Utilisations du fichier .DPR pour l'application principale et la DLL.



0
votes

Juste pour ajouter un seul fait:

Delphi vous permet d'attribuer simplement pCHAR à une chaîne de sorte que sur le côté DLL, vous n'avez pas besoin de typée: xxx

Cela s'applique également à la transmission de Pchak comme paramètre à une fonction qui attend une chaîne (par valeur).


0 commentaires