Posté le 15/07/2017 13:54
Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 118 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements
Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd
Citer : Posté le 14/07/2021 21:33 | #
J'ai essayé de faire un truc comme Utilities(https://github.com/gbl08ma/utilities/blob/master/src/memsysGUI.cpp#L373)(ca me lache juste un your thing is: et rien d'autre)
void getUserInfo(char* output) {
char* flagpointer = (char*)0x80BE0000;
int counter = 0;
while(*flagpointer == 0x0F) {
flagpointer += 0x40;
counter++;
}
if(counter) {
flagpointer = flagpointer - 0x40;
if(*(flagpointer+0x18) != '\0') {
output = (flagpointer+0x18);
}
}
}
mais ca marche pas(meme avec un gint_world_switch)
int main(void) {
dclear(C_WHITE);
char* e = malloc(32);
for(int i = 0; i < 32; i++) *(e + i) = '\0';
gint_world_switch(GINT_CALL(getUserInfo, e));
dprint(1, 16 * 1, C_BLACK, "your thing is: %s", e);
dupdate();
getkey();
return 1;
}
(me tuez pas parceque y a une fuite de mémoire parceque je le sais déja)
Citer : Posté le 14/07/2021 21:36 | #
Pour accéder à la mémoire comme ça tu n'as pas besoin de changer de monde, tu peux le faire directement.
Sinon, il se peut que les informations aient bougé sur l'OS plus récent de la Graph 90+E ou que la transcription soit imprécise. Tu peux essayer de lancer Utilities sur ta Graph 90+E pour voir s'il le trouve déjà.
Citer : Posté le 14/07/2021 21:39 | #
Les informations sont correctes sur Utilities
sinon j'ai trouvé ca
https://prizm.cemetech.net/index.php?title=User_Name_Registry
Citer : Posté le 07/09/2021 19:15 | #
Bonjour,
j'essaye de me lancer dans la création d'add in pour un Casio 90+E (j'ai cru comprendre que gint était soit le seul à permettre ça soir le meilleur) je suis un peut le tutoriel de Lephenixnoir sauf qu'au moment de compiler l'add in (que ce soit en avec build-fx ou buid-cg) j'ai une erreur avec make qui me dit:
Étant débutant avec make (ou Linux en général) je ne sait pas comment régler cette erreur
si cela peut aider, j'ai installer fxsdk et gint avec l'outil giteapc de lephenixnoir
Citer : Posté le 07/09/2021 20:11 | #
Salut ! Pour la Graph 90+E il y a aussi le PrizmSDK, mais c'est probablement plus difficile à utiliser que gint à ce stade, donc oui il n'y a pas d'alternative évidente.
En lisant le tutoriel, je réalise que je n'ai pas indiqué que tu dois te rendre dans le dossier du projet avant de taper fxsdk build-cg.
% cd mon-projet # <- ça !
% fxsdk build-cg
fxsdk build-cg cherche un projet fxSDK dans le dossier courant, et ce que tu peux retenir quand tu vois cette erreur c'est qu'il n'en a pas trouvé.
Je pourrais améliorer le message d'erreur dans cette situation, aussi...
Citer : Posté le 07/09/2021 21:42 | #
Salut ! Pour la Graph 90+E il y a aussi le PrizmSDK, mais c'est probablement plus difficile à utiliser que gint à ce stade, donc oui il n'y a pas d'alternative évidente.
En lisant le tutoriel, je réalise que je n'ai pas indiqué que tu dois te rendre dans le dossier du projet avant de taper fxsdk build-cg.
% cd mon-projet # <- ça !
% fxsdk build-cg
fxsdk build-cg cherche un projet fxSDK dans le dossier courant, et ce que tu peux retenir quand tu vois cette erreur c'est qu'il n'en a pas trouvé.
Je pourrais améliorer le message d'erreur dans cette situation, aussi...
Ok, merci, je pensait qu'il fallait rester dans le dossier ou on faisait la commande fxsdk new mais c'est vrai que c'est un peut plus logique d'aller dans le dossier du projet ^^'
Citer : Posté le 14/09/2021 23:34 | #
Bonjour, j'ai un problème qui apparait après avoir ajouté un timer.
Mon objectif est d'avoir scene_map.draw qui tourne à fond, et scene_map.update à fps constant.
Je m'y suis bien pris ?
Merci
int timer = timer_configure(TIMER_ANY, 25*1000, GINT_CALL(callback_tick));
timer_start(timer);
// boucle principale
while (1)
{
clearevents();
if (keydown(KEY_EXIT))
break;
if (keydown(KEY_MENU))
gint_osmenu();
scene_map.draw();
}
timer_stop(timer);
...
static int callback_tick()
{
scene_map.update();
return TIMER_CONTINUE;
}
Exception !
TLB miss read
PC 00302590
TEA ca8475bc
TRA 0
Citer : Posté le 15/09/2021 07:27 | #
C'est pas mal, cette partie timer semble tout à fait correcte. Par contre tu as un problème évident d'accès concurrent si scene_map.draw() se fait interrompre par scene_map.update(). En particulier si des pointeurs bougent durant l'update alors que tu étais en train de les utiliser durant l'affichage.
Tu peux déterminer dans quelle fonction le crash se produit en lisant le fichier build-fx/map (s'il est généré) et en regardant dans quelle fonction l'adresse 00302590 tombe.
Citer : Posté le 16/09/2021 22:19 | #
Ok merci de ta réponse. C'est en effet le cas, scene_map.draw se fait interrompre sans cesse. Normalement rien ne bouge à ce niveau là. C'était déjà comme ça de cette façon avant
Ok excellent, toutefois, 00302590 tombe entre deux
0x00000000003026e4 __ZN8Windmill21render_triangle_blackEP6VertexS1_S1_
Il y a d'autres astuces de debug de ce style ?!
Citer : Posté le 16/09/2021 22:23 | #
Très bien, la valeur indiquée à gauche est l'adresse où la fonction commence. Donc c'est la première des deux.
Au fait tu peux utiliser c++filt pour avoir les jolis nom :
(...)
0x0000000000302152 Windmill::render_triangle_texture(Vertex*, Vertex*, Vertex*, Texture const*)
0x00000000003026e4 Windmill::render_triangle_black(Vertex*, Vertex*, Vertex*)
(...)
Donc c'est le render_triangle_texture(). D'après l'erreur (TLB miss read), tu accèdes à une adresse invalide, qui est notée dans TEA, et est donc ca8475bc. Cette valeur n'est pas une adresse qui a du sens, et ce n'est pas non plus du code. Je suggère de regarder si jamais tu n'aurais pas des choses non initialisées en rapport avec tes textures.
Citer : Posté le 12/11/2021 01:04 | # | Fichier joint
Salut Lephé,
J'ai toujours des exceptions du même type que dans les messages précédents..
J'ai passé la soirée dessus et je trouve pas d'où ça peut venir donc j'aurai bien besoin d'un petit coup de main
L'exception surgit après un temps aléatoire. Je lance l'addin puis je touche à rien, et au bout de 10s, 15s, 1 minute ou 5 minutes l'exception apparait.
"Read address error PC 00301060 TEA 88024eda"
"Read address error PC 00301096 TEA 88023ede"
Ça tombe sur clip_viewport_inside_edge() ce coup ci, mais à d'autres moments ça tombe dans copy_vertex()...
"TLB miss write PC 0030c5b6 TEA c0423d38"
J'ai l'impression que le problème vient de memcpy qui renvoie par moment une valeur abérante. Je ne sais pas si c'est possible.
Ces exceptions ont été obtenues avec le même g1a, juste relancé plusieurs fois.
Est-ce que tu saurais me dire ce qu'il se passe ? (zip en pj)
Autre chose, %f n'est pas implémenté pour sprintf ? Je n'arrive pas a afficher un float
Citer : Posté le 12/11/2021 11:36 | #
Intéressant... j'ai commencé à regarder, pour l'instant je peux pas reproduire le bug mais on va voir.
Pour %f, c'est implémenté mais pas activé par défaut parce que y'a des tables qui prennent de la place.
int main(void)
{
__printf_enable_fp();
// %f, %e, %g disponibles
}
Citer : Posté le 12/11/2021 12:33 | #
Ok merci
Est-ce qu'il y a d'autres astuces de debugages ?
Est-ce que l'on peut faire un bloc try/catch comme en C# par exemple pour isoler des bouts de code ?
Parce que j'ai un peu de mal à décortiquer le problème quand j'ai un crash. Je ne sais pas quelle variable pose problème
Citer : Posté le 12/11/2021 12:46 | #
Il n'y a pas grand-chose malheureusement. C'est un peu le principe du C (là tu fais du C++ mais t'es bien plus du côté C que C++) : on se donne des «comportements indéterminés» justement comme un tradeoff entre l'optimisation et la facilité à débusquer les erreurs. Les tableaux ne testent pas leurs bornes par exemple, ce qui va plus vite, mais si tu lis une valeur à un indice invalide tu obtiens n'importe quoi, ton code continue avec ce n'importe quoi, et c'est toi qui dois remonter le bug ensuite.
Pour les exceptions C++, il faudrait du support explicite côté gint, qui n'existe pas. C'est assez compliqué, même franchement très compliqué.
Dans mon expérience, il y a deux parties à la compréhension d'un bug/crash : bottom-up et top-down. Bottom-up c'est quand tu pars des infos du crash, que tu devines le type d'erreur possible, et que tu remontes à la source. Top-down c'est quand tu regardes le code sans t'appuyer sur la nature du bug et que tu détermines où est-ce que le code ne fait pas ce que tu veux, et que tu descends vers le bug. Y'a plein d'outils à la con entre les deux, y compris commenter du code, intégrer des fonctionnalités d'introspection (ce que je pense est très sous-estimé), et rajouter des vérifications runtime/assert/etc.
Dans tous les cas, le plus important, et ça doit toujours être la première chose à mon avis, c'est la reproductibilité. Plus tu arrives à reproduire le bug de façon consistante et rapide, plus tu pourras faire plein de tests et acquérir plein d'informations pour comprendre le bug. Pour l'instant ça fait 1 heure que le code tourne sur ma Graph 75+E et il n'a pas planté. Je tente sur une SH3...
Citer : Posté le 13/11/2021 11:18 | #
Ok il y a donc pas trop d'autres astuces. Les techniques que tu décris c'est déjà ce que je fais en parti 🙂
Mais c’est bien là le problème.
Ça arrive au bout de X itérations du code. Impossible d'afficher à chaque frame la valeur des variables. Si ça arrive au bout de 5000 itérations le bug je serai mort de vieillesse avant haha
D'autant que je n'avais pas de problème avant la migration. Du coup ça ne peut pas venir d'une faille algorithmique.
Sinon, comment je peux faire si je veux vérifier si une adresse est déconnante ?
La il semblerait que dans memcpy j'ai des adresses aberrantes qui arrivent.
Un if((uint)ptr1 > ?)
Afin d'attraper les erreurs 🙂
Ok, tant mieux.
Tu me diras ce que ça rend en SH3
Citer : Posté le 14/11/2021 11:29 | #
Du coup le bug se produit bien sur SH3, par contre le temps que ça prend est très difficile à prévoir comme tu l'as annoncé. Tu peux utiliser Ftune pour accélérer le code pour atteindre plus vite le point de bug si c'est suffisamment déterministe.
Voilà quelques infos supplémentaire pour te montrer comment je debugge, en espérant que ça aide. On part de ça :
"Read address error PC 00301096 TEA 88023ede"
Ça tombe sur clip_viewport_inside_edge() ce coup ci, mais à d'autres moments ça tombe dans copy_vertex()...
"TLB miss write PC 0030c5b6 TEA c0423d38"
Pour rappel dans le cas d'une erreur mémoire, TEA contient l'adresse incriminée. Les adresses 88024eda et 88023ede sont dans la RAM, mais ne sont pas alignées (multiples de 4). Si tu regardes le code à l'endroit annoncé :
# Ensuite chercher l'adresse : taper "/301060" puis Entrée
Tu peux voir que c'est du mov.l, et le .l (long) indique que c'est 4 octets qui sont lus ou écrits. Ici les adresses ne sont pas multiples de 4, c'est donc ça l'erreur.
Si tu regardes clip_viewport_inside_edge() tu verras que ça concerne la lecture ou l'écriture des composantes du sommet. Pour la lecture à 301060, c'est raisonnable parce que c'est la première de la fonction. Pour l'écriture à 301096, tu vois que ça n'a aucun sens. La donnée accédée c'est @(4,r5) (le @ indique qu'on fait un accès mémoire). Cette notation un peu exotique signifie juste r5+4. Sachant que dans une fonction les paramètres c'est r4, r5, r6 et r7 dans cet ordre, c'est le deuxième paramètre. (Ici le this de la classe est implicitement le premier paramètre, donc c'est le Vertex *). Et donc, on lit 4 octets à la position 4 dans vertex, c'est-à-dire vertex->y. Ça n'a pas de sens parce qu'il y a déjà une lecture à cet endroit plus haut dans la fonction (pour le test) et elle elle n'a pas planté.
En général quand il y a un bug comme ça qui n'a pas de sens par rapport à la sémantique du langage C, c'est qu'il y a une arnaque dans l'assembleur. Et si le bug n'a pas de sens non plus par rapport à la sémantique du langage assembleur, c'est qu'il y a une arnaque de non-déterminisme/interruption/concurrence. Ici en gros on se dit qu'une interruption a pu modifier la valeur de r5. Mais tu n'utilises pas de timers donc c'est assez douteux (il faudrait que ce soit un bug dans gint, ce qui est possible mais pas encore la piste privilégiée).
Pour la dernière adresse c'est dans memcpy(). Parfois GCC émet des appels à memcpy() quand tu demandes de copier des structures, mais toi tu écris généralement le memcpy() à la main. On peut aussi chercher "memcpy" dans le code désassemblé et tous ceux qui sont dans ton code sont écrits à la main. Et tu copies quoi ? Soit la caméra (Windmill::copy_camera), soit des sommets (Windmill::swap_vertex, Windmill::copy_vertex).
Je remarque que tu n'as pas perdu ton temps et debuggé les adresses dans Windmill:copy_vertex. Pour pouvoir les lire il faut les afficher en hexadécimal, ie. avec "%08x" (ou %p). Aussi, tu t'es trompé sur la valeur à afficher :
{
dprint(1, 1, C_BLACK, "%d", &vertex_source);
dprint(1, 8, C_BLACK, "%d", &vertex_dest);
memcpy(vertex_dest, vertex_source, sizeof(Vertex));
}
Ici vertex_source et vertex_dest sont deux pointeurs de 4 octets chacun, dont la valeur c'est l'adresse d'un Vertex (de 24 octets). Ce que tu veux afficher c'est leur valeur exacte. Ici tu affiches leur adresse, qui est sur la pile (puisque c'est sur la pile que sont stockées les variables locales et arguments de la fonction). C'est bien leur valeur que tu dois afficher, ce qui se voit d'ailleurs au fait que c'est leur valeur que tu passes à memcpy().
dprint(1, 8, C_BLACK, "%08x", vertex_dest);
Cela dit, si tu fais ça toutes les valeurs s'écrivent les unes sur les autres. Mais c'est déjà un début, tu peux notamment voir que le dernier chiffre est toujours soit 0 soit 8, donc c'est aligné.
Pour répondre à ta question, qu'est-ce qu'on pointeur valide ? C'est compliqué parce qu'il y a plein de régions valides (voir cette technique pour les détails sur SH4). Mais ici on peut viser vraiment simple :
Par expérience tu peux regarder les premiers caractères et tu sauras. 003 → code et données constantes ; 081 → globales ; 80 ou 81 → ROM ; 88 → RAM.
Donc par exemple si on regarde les valeurs de TEA que tu as vu, les deux premières c'est clairement dans la RAM, et la dernière (0xc0423d38) c'est du BS complet ça n'a rien à avoir avec une adresse mémoire. (Ce n'est pas non plus du code, si tu te demandais.)
Bien, donc le point commun dans tout ça semble quand même être les sommets. Avant de continuer, je devrais te mentionner que tu peux tout à fait copier des structures avec =, puisque le compilateur génère un constructeur par copie et un opérateur d'assignement triviaux par défaut :
v1 = v2;
// Pareil que copy_vertex(v2, v1);
Pas besoin de t'embêter à écrire copy_vertex() à chaque fois. Ça revient au même (memcpy()), mais c'est plus lisible.
Dans les appels à copy_vertex(), il y a pas mal de tableaux et souvent la taille est limitée à 10, alors que la taille des entrées/sortie varie parfois pas mal. La taille commence à soit 3 soit 4 selon le type de primitive, et ensuite elle peut augmenter si le clipping t'intersecte le triangle et force une séparation. J'ai rajouté un test explicite sur le nombre de sommets (ie. si on dépasse 5 on arrête le programme), mais j'arrive à planter dans memcpy() sans déclencher ce bug, donc c'est probablement pas ça. J'ai aussi ajouté des gardes sur les memcpy(), dans Windmill::swap_vertex() et Windmill::copy_vertex() mais ça n'empêchait pas les bugs.
Pendant que j'y pense, ce n'est pas parce que tu n'avais pas le bug avant qu'automatiquement le code est clean. En changeant de compilateur (SDK → GCC), tu peux voir arriver des bugs qui ont toujours été là mais qui ne se voient que parce que le nouveau compilateur optimise plus. Bien sûr ça peut aussi être un bug à la con dans gint par exemple.
À ce stade j'ai croisé diverses autres erreurs, quasiment toujours sur des accès mémoire sur des sommets. Je ne vois pas grand-chose de plus à faire en bottom-up, je vais commencer à bisect à mort et on verra si je trouve.
Citer : Posté le 14/11/2021 20:31 | #
Merci tous les détails, très instructif.
J'en apprend un peu plus à chaque fois
J'affiche les valeurs, mais sans trop savoir ce qu'il faut voir en fait. Là c'est un peu plus clair.
En effet, j'ai désactivé la partie avec le timer au cas où ça puisse avoir une influence.
Etrange que l'accès à vertex->y provoque le bug en effet, j'y accède sans cesse. Pourquoi il buggerait soudainement au bout de X temps ?
J'ai mis une limite à 10 car un triangle ne peut pas être découpé en plus de 10 sous triangles, donc normalement le problème ne peut pas venir de là. D'autant plus que le bug apparait même si tu bouges pas la caméra (= le triangle noir affiché est intact = 3 vertex < 10)
C'est surtout ça qui me chagrine, c'est l'aspect aléatoire. J'ai la main pour le debuggage de logique du code, pas sur les tréfonds
C'est sans doute un problème profond si il n'apparait que sur SH3. Une histoire de compilateur ou ce genre de chose j'imagine ...
Merci de chercher bon courage
Citer : Posté le 14/11/2021 21:47 | #
Parmi les bugs que j'ai croisés, un est surprenant :
PC :0030819a
TEA :6030eeec
TRA :00000000
Ça tombe (dans mon build) dans topti_split(), une sous-fonction de dprint(), au moment de lire les données de la police. Le truc un peu frappant c'est que l'adresse 0x6030eeec, qui ne ressemble à rien, ressemble quand même à 0x0030eeec, qui est tout pile dans les données de la police. On dirait donc que l'adresse a été "modifiée", et ça c'est pas ton code puisque tu n'y accèdes jamais (genre par dfont()).
À ce stade vu la variété des lieux de crashs, des objets impliqués, et le délai très variable, ça ne peut être qu'un bug de gint ou un problème de corruption dans ton add-in (lesquels sont en général soit des problèmes avec les timers soit des dépassements de tableaux sur la pile).
J'ai réussi à obtenir un crash similaire dans gintctl donc... c'est probablement là qu'est le problème. Mais pour l'instant je n'ai pas réussi à l'obtenir avec des versions récentes, donc j'ai continué sur Windmill. Sur SH4 j'ai fait tourner le programme pendant 5 heures sans problème donc ça devrait le faire. Quand j'aurai trouvé le bug on pourra sans doute confirmer que c'est SH3 uniquement.
J'ai réussi à avoir le même crash (parfois avec 0x4030eeec) avec quasiment pas de code de dessin. Mais où est l'octet écrasé (le premier octet de l'adresse) ? Il est possible qu'un dépassement de tableau sur la variable stockée avant cause la corruption. Et la variable avant, c'est... yup, la VRAM. Probablement pas une coïncidence ça.
J'ai réussi à réduire le bug (qui tombe toujours dans topti maintenant) en retirant tout le code de dessin sauf un pauvre dclear() et le copy_camera(). Comme ça tourne beaucoup plus vite j'arrive parfois à avoir le bug en moins d'une minute, ce qui est vachement agréable par rapport à une demi-heure...
Je m'arrête là pour l'instant, je te dirai quand j'en saurai plus. Pour l'instant fais comme si le bug n'existait pas, je m'en occupe. Selon toute probabilité la source est dans gint de toute façon.
Citer : Posté le 21/11/2021 16:10 | #
Il n'y a pas de classe en C
Si tu y tiens utilise le C++ (initialement appele C with classes)
mais sinon il y a les struct qui te permettent de creer tes propres types de donnees
Citer : Posté le 21/11/2021 16:49 | #
Oui je tiens a utiliser les classes mais je parviens pas a compiler avec Gint
Albert Einstein
Citer : Posté le 21/11/2021 17:12 | #
pourquoi est-ce que ce bout de code
dline(134, 99, 139, 99, C_BLACK);
affiche des lignes plus fines que ce bout de code ?
dline(256, 123, 251, 123, C_BLACK);