Tableau en C

Hello,

Je suis en face d’un petit problème de programmation, et afin de mieux comprendre mon cas, je me pose la question suivante :

Lorsque l’on délare un tableau avec un variable non définie à la compilation (taille venant d’un fichier externe), que fait le compilateur ? Il alloue une taille par défaut au tableau ? Car ensuite, lorsque je lance le programme sur ma machine, pas de problème, mais lorsque je lance sur une sun vieille, segmentation fault. La taille de la variable est assez grande, et je pense que la taille allouée par défaut est trop petite, d’où seg fault. Et que donc il faut que je fasse un malloc.

Ai-je juste ?

Merci d’éviter les conneries de gosse de douze ans dans le titre des threads. La prochaine fois je me pose pas de questions et je delete tout.

Hé ben… c’est sérieux ici. Je note pour le prochain post.

Le compilateur, s’il respecte la norme, n’accepte que les valeurs statiques (constantes) comme déclarateurs de taille. GCC, par exemple, y déroge:

int x = 5; //ou tout autre calcul int tab[x]; //ca passe, c'est "mal"

Je ne vois pas en quoi ca explique le bug rencontré, mais puisque c’est mal, ne recommence pas. B)

Oui, malloc et reallloc sont faits exprès pour gérer des tableaux dont la taille n’est connue qu’à l’exécution du programme (veleurs dynamiques, genre, calcul de longueur d’un fichier passé en argument) et non pas à la compilation (valeurs statiques). Ce sont tes nouveaux amis maintenant. :smiley:

Purée, t’avais mis quoi pour énerver Yavin (qui prend une majuscule au passage, ca lui apprendra)

Comme le dit vectra c’est interdit dans le C Ansi (celui de 89 donc), mais GCC a une extention qui lui permet de le faire : http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gc…ble-Length.html

C’est surement pour ça que ça ne fonctionne pas sur ta machine sun.

[quote=“kineox, post:6, topic: 29796”]Comme le dit vectra c’est interdit dans le C Ansi (celui de 89 donc), mais GCC a une extention qui lui permet de le faire : http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gc…ble-Length.html

C’est surement pour ça que ça ne fonctionne pas sur ta machine sun.[/quote]

Ca impliquerait qu’il ait pas gcc sur le Sun, parce qu’à moins d’une grosse différence de versions, ca devrait marcher pareil.
Mais p’tet bien que Mav’ a utilisé cpp (?), le compilateur par défaut sous les vieux systèmes Sun. C’est vraiment de la merde complètement pas standard, au point de rendre la plupart des codes non portables. Mais j’imagine que ca doit quand meme être optimisé à fond pour SPARC (sinon, aux… fraises!).

comme dit plus haut, malloc est fait exactement pour ca

[quote=“vectra, post:7, topic: 29796”]Ca impliquerait qu’il ait pas gcc sur le Sun, parce qu’à moins d’une grosse différence de versions, ca devrait marcher pareil.
Mais p’tet bien que Mav’ a utilisé cpp (?), le compilateur par défaut sous les vieux systèmes Sun. C’est vraiment de la merde complètement pas standard, au point de rendre la plupart des codes non portables. Mais j’imagine que ca doit quand meme être optimisé à fond pour SPARC (sinon, aux… fraises!).[/quote]
Ben j’ai compilé avec gcc sous SUSE 10.0. Et compilé avec gcc sous solaris je sais pas combien. SUSE tourne sur mon dell, centrino 1.8, 1go ram. Pas de problème. Sur les machines sun : seg fault…

Je vais modifier mon code.

[quote=“vectra, post:7, topic: 29796”]Ca impliquerait qu’il ait pas gcc sur le Sun, parce qu’à moins d’une grosse différence de versions, ca devrait marcher pareil.
Mais p’tet bien que Mav’ a utilisé cpp (?), le compilateur par défaut sous les vieux systèmes Sun. C’est vraiment de la merde complètement pas standard, au point de rendre la plupart des codes non portables. Mais j’imagine que ca doit quand meme être optimisé à fond pour SPARC (sinon, aux… fraises!).[/quote]
L’extension a pu être ajoutée dans des versions plus récentes de GCC.
Et le compilateur de Sun ça doit tout simplement être cc, puisque cpp doit être le C PreProcessor comme sur les autres UNIX.

Oui, c’est bien lui. Le salaud, il m’a fait perdre du temps avant qu’on m’installe enfin gcc.

Oui!
Très utile pour déboguer les macros B)

Bon, sinon, vive malloc/free, hein?

pour les fainéants:

[code]#include <assert.h>

// definition d’une macro

#define ARRAY_ALLOC(TAB, DIM, DATATYPE)
assert(TAB = (DATATYPE *) calloc(DIM, sizeof(DATATYPE)));

int
main(void)
{
int *tableau;
ARRAY_ALLOC(tableau, 15, int);

}[/code]

B) RAAAH !! Gros malade !!

JAMAIS de code indispensable au déroulement d’un programme dans un assert !

[quote=« Drealmer, post:12, topic: 29796 »]B) RAAAH !! Gros malade !!

JAMAIS de code indispensable au déroulement d’un programme dans un assert ![/quote]
:smiley:

Oui en effet, la macro assert est dépendante de la directive NDEBUG. Si NDEBUG est définie, ton code entre parenthèses n’est plus généré (donc plus déroulé).

Il faut faire un truc de type

assert( my_variable != NULL );

Sachant que my_variable ne peut pas être NULL par construction. Je veux dire par là, qu’il ne faut que la valeur NULL soit dans le domaine des valeurs acceptées.

J’ai bien vérifié: cpp mange le code dans le corps de l’assert si on définit NDEBUG avant l’inclusion d’assert.h.

Pourtant, assert, c’est du genre utile et recommandé. C’est souvent enseigné (sans le NDEBUG hélas) pour arrêter un programme quand un point absurde est atteint, et ce en routine, pas en déboguage (gdb se débrouille pas mal). Pourtant, je viens de voir qu’assert n’est supposé être qu’un mécanisme de déboguage, et non pas un raccourci syntaxique tres (tres) commode.

Donc, pour faire correctement ce que j’ai commis, il faudrait ecrire une autre macro assert2 qui fait comme assert (affichage de fichier, ligne, exit) et serait insensible au NDEBUG…

Non non, pas du tout. Il suffit de faire ce que j’ai voulu exprimer. Tu écris le code effectif (ici ton malloc) et tu testes son retour dans un assert.

L’idée c’est que assert sert à vérifier que tout se passe comme prévu, et cette vérification peut éventuellement être coûteuse en termes de temps. Je prends un exemple, dans mon code actuel, j’utilise un vecteur d’élements, dans lequel chaque élément ne devrait se retrouver qu’une seule fois au maximum si mon programme fonctionne comme j’ai prévu. Bon, ben j’ai une assert de ce genre, qui se déclenche à chaque modification du vecteur:

C’est très coûteux (O(n)), et ça sert clairement à rien d’autre qu’à vérifier que tout se passe comme prévu. Une fois qu’on est sûr de soi, on vire ça de la release, et hop. Ca tombe bien, assert a été prévu dans cette optique.

Bon maintenant, c’est l’idée de base derrière assert ça. La façon de repérer et de gérer les erreurs avec des assert, des exceptions, de la résilience, des chaînes de return, etc. c’est probablement un des sujets qui génère le plus de discussions depuis l’invention de l’informatique.

Voilà l’exécution dans le terminal : (analyse plus bas)

[116]in1sun1-amstutz% stage2 problem003-500.dat 33 2 0 1 1
Start
TailleV Start
TailleV End // recuperation des tailles nombre_requetes, nombre_alternatives, nombre_ressources
Declaration Structures
nombre requetes : 500 nombre alternatives : 1905 nombre ressources : 9
requetes // int requetes[nombre_requetes][NOMBRE_COLONNES_REQUETES];
alternatives // int alternatives[nombre_alternatives][NOMBRE_COLONNES_ALTERNATIVES];
requetes ordrees // int requetes_ordrees[nombre_requetes];
solutions initiales // int solutions_initiales[nombre_requetes][nombre_resources];
requetes out // int requetes_out[nombre_requetes];
matrice interaction // int matrice_interactions[nombre_alternatives][nombre_alternatives];
Segmentation fault (core dumped)

Ce qui en ressort, c’est que parfois ca passe, et une fois non… donc je ne pense pas qu’il s’agisse d’un problème de compilateur ou de standard ! J’ai pensé que les matrices dont les deux dimensions étaient non-statiques posaient problème, mais la matrice solutions_initiales présente ce cas, et ne pose pas problème…

Mystère ?

Z’y-va, sort GDB!

Sérieux, pour voir OU un programme plante exactement, faut un débogueur. Histoire de savoir quelle est l’instruction en cause, pis d’inspecter les valeurs en cours pour comprendre ce qui foire.

En tous cas, c’est signe qu’il y a un blème (on apelle ca un ‹ état indéterminé ›, non?).

Drealmer

Ok, j’avais interprêté assert selon mon intérêt. Dans ma tête à moi, ca a quand même un sens de stopper un programme systématiquement dès lors qu’une allocation indispensable est refusée, mais ce n’est pas le but d’assert, semble-t-il. J’ai de l’upgrade à faire…

Ben c’est qu’en fait je lance mon code par vpn/ssh là, sur la sun distante. Et je vois pas comment utiliser de debuger. Et que j’utilise le debuger Eclipse sur SUSE sur mon portable, mais là le code passe nickel.

Gdb quikrefs:

Voir aussi la refcard sur: http://refcards.com/refcards/index.html

Ca passe nickel en mode texte, même si c’est quand même mieux à travers un IDE.