Tableaux de chaînes et CopyMemory, ou quand le potence vous guette...

nonopirator
Messages postés
6
Date d'inscription
lundi 14 février 2005
Statut
Membre
Dernière intervention
29 juin 2010
- 27 nov. 2008 à 20:34
nonopirator
Messages postés
6
Date d'inscription
lundi 14 février 2005
Statut
Membre
Dernière intervention
29 juin 2010
- 2 déc. 2008 à 18:39
Bonjour,


Après une journée de tests et de recherches, je passe au plan B: Vous, mes sauveurs!!(Déconnez pas, hein?!)
J'ai une appli statistique qui manipule des (très) grands tableaux de Single et de String.
Ces tableaux sont statiques, la taille des chaînes est définie, donc du genre:
Dim MyArray(1 to X) As String * Y
L'origine du mal est que j'ai besoin, parfois, souvent même, d'insérer un élément.
J'avais en premier lieu fait une fonction qui part de le fin jusqu'à l'index de l'élément à insérer(step -1) et qui décale donc tous les éléments "d'un cran vers la droite". Vous me suivez?
Bon, ça marche, certes, mais un demi million d'éléments à décaler plusieurs centaines de fois, VB il aime pas du tout!!
Mon idée était donc de faire un CopyMemory pour décaler toutes les données qui suivent la position d'insertion d'un cran vers la droite...

Le résultats, pour un tableau de Single, donnc ceci:

    Taille = 4 ' Car 4 octets par Single
    AdrEltD = VarPtr(QtéCash_DC_NL(Ligne + 1))
    AdrEltS = VarPtr(QtéCash_DC_NL(Ligne))
    CopyMemory ByVal AdrEltD, ByVal AdrEltS, Longueur * Taille 'Longeur= Nombre d'elts à décaler

Et ça marche pas... si mal que ça!! :-)

Le problème intervient quand il s'agit de faire la même chose avec des chaines de type String * 10

J'ai essayé avec des String tout court(ficelle!) en faisant exactement la même chose et ça fonctionne aussi(plutôt que de copier des Single 4 Octets je copie des adresse de descripteurs de chaînes, ça semble cohérent...
Ca fonctionne mais quelques secondes après VB plante brutalement???
Avec des String * 10, y'a rien qui marche, même AdrEltD VarPtr(QtéCash_DC_NL(Ligne + 1)) ne fonctionne pas car j'ai au final AdrEltD AdrEltS!!

Enfin bref, je vais pas détailler tout ce que j'ai essayé...

Si quelqu'un a une solution, je lui ferai pas un bisou mais l'intention y serait!!!

PS: pour les petits malins tentés de répondre "Rho ben normal y'a pas de Redim donc il copie en dehors de l'espace réservé..." et ben sachez que dans le principe, vous avez raison... mais que mon tableau est plus grand que ce dont j'ai besoin et je fais mon CopyMemory que qur les éléments réellement utiles, donc à l'interieur de l'espace réservé...

Pour imager: j'ai un tableau T(1 to 10) As Single
Je n'ai réellement que 6 éléments.
J'insert en 3
Je copie donc 4*4 Octets de @T(3) vers @T(4) donc T(3)->T(4), T(4)->T(5), T(5)->T(6), T(6)->T(7) et T(3) = Valeur insérée

Voilà, merci d'avance!!

Carfman

4 réponses

PCPT
Messages postés
13280
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
3 février 2018
49
27 nov. 2008 à 21:01
salut,

il y a quelques temps j'étais confronté au même problème et avec notre gentil Jack national on s'est creusé la tête plusieurs heures..., avec trop peu de résultats probants....

en passant du SAFEARRAY à toute la panoplie des API non documentées... connues, échec.
avec des LONG, comme une lettre à la poste
mais avec des string, confrontés à la structure BSTR, de mémoire, qui semble plus qu'indigeste pour VB.
du moins c'est ce qui résultait des tests effectués
si je ne confonds pas (bstr), alors voir ici : http://msdn.microsoft.com/en-us/library/ms221069.aspx

je dois encore avoir les tests faits, quelque part...., je peux te les fournir si tu veux (et si je les retrouve :D)
++

<hr size="2" width="100%" />
Prenez un instant pour répondre à [sujet-SONDAGE-POP3-POUR-CS_769706.aspx ce sondage] svp 
0
PCPT
Messages postés
13280
Date d'inscription
lundi 13 décembre 2004
Statut
Membre
Dernière intervention
3 février 2018
49
27 nov. 2008 à 21:17
re,

exemples (tests) retrouvés mais pas propres, inutilisables, çà va te perdre plus de temps qu'autre chose

voici les 2 liens qui ont été les plus précis, mais faut avoir le coeur accroché et aimer mélanger café et aspirine...

http://www.codeguru.com/vb/gen/vb_misc/algorithms/article.php/c7495/
http://oreilly.com/catalog/win32api/chapter/ch06.html#61581

ps : en bas du premier lien tu trouveras un code VB6 testable...

bon courage, je suis le fil de près

<hr size="2" width="100%" />
Prenez un instant pour répondre à [sujet-SONDAGE-POP3-POUR-CS_769706.aspx ce sondage] svp 
0
nonopirator
Messages postés
6
Date d'inscription
lundi 14 février 2005
Statut
Membre
Dernière intervention
29 juin 2010

1 déc. 2008 à 15:06
Bonjour bonjour,

Merci pour ces infos, j'étais en RTT Vendredi donc j'ai pas encore eu le temps de m'y repencher, mais je fais ça dans la semaine!
J'ai quand même regardé les liens. Je pense qu'il y a moyen là dedans de faire avec des VarPtr et des CopyMemory ce qu'on fait avec des simples affecations d'éléments de tableaux de chaînes, certes plus rapide mais il faudra toujours passer par des boucles pour insérer un élément.

Sauf erreur de ma part, cela ne m'explique pas pourquoi si je change, par CopyMemory, l'adresse du descripteur de chaîne pointé par l'élément du tableau, cela fonctionne(je le constate dans la fenêtre espion, mais VB plante quelques seconde après!

A bientôt!

Carfman
0
nonopirator
Messages postés
6
Date d'inscription
lundi 14 février 2005
Statut
Membre
Dernière intervention
29 juin 2010

2 déc. 2008 à 18:39
ALLELUIA!!

Bon, ça marche!!!
Je mets la solution au cas où quelqu'un en aurait beasoin...

Ce qui merdait:
Par exemple, j'ai un tableau T(1 to 5) As String
Je n'ai réellement que 4 éléments utiles: de 1 à 4
J'insert un élément entre 2 et 3
Je fais un CopyMemory ByVal VarPtr(T(3)), ByVal VarPtr(T(2)), 12
Cela a pour effet de décaler les adresse de descripteurs de chaînes pointés par T(n)
Ce qui me fait T(2)=>T(3), T(3)=>T(4) et T(4)=>T(5)
Mais le problème est que VB plantait quelques secondes après... Pourquoi?
Et ben parce que T(2) pointait vers le descripteur D2 et après CopyMemory, T(3) pointait lui aussi vers le descripteur "anciennement" D2... donc quand j'affecte ma nouvelle valeur à insérer à T(2), VB remplace "l'ancien D2" par le "nouveau D2" et supprime l'ancien D2 de la mémoire et S2 sur laquelle il pointe puisqu'il croit que tout cela ne sert plus, T(3) se retrouve donc à ne plus pointer sur rien d'où plantage au bout de quelques secondes le temps que VB ait besoin de la valeur de T(3) en mettant à jour la fenêtre espion, sauf que c'est pas T(3) mais T(286452), ça prend un peu de temps!!

La solution était tout simplement de récupérer l'adresse du descipteur(D5) pointé par T(5), de faire le décalage, et de faire ensuite pointer T(2) sur l'ancien D5, ce qui fait que chaque vache a son petit(du moins un petit, même si c'est pas le sien, mais les vaches s'en moquent...)

Voili voulou!!

Carfman
0