OVH Cloud OVH Cloud

Erreur que je comprends vraiment pas!!! HELP !

22 réponses
Avatar
amplitude
Bonjour, voici mon code :

for(int i=3D0;i<Tbl.Rows.Count;i++)
{
Tbl.Rows[i][0] =3D "0";
}

Je pr=E9cise que j'ai 4 colonnes dans ma table, je l'ai bien v=E9rifi=E9e=
=2E

Il me dit l'erreur suivante sur la ligne Tbl.Rows[i][0] =3D "0" :

An unhandled exception of type 'System.StackOverflowException' occurred=20
in system.windows.forms.dll

Dans le debugg, je peux voir que le i est =3D =E0 0, donc ca a prioris d=
ans=20
le premier passage de la boucle.

J'ai donc essayer en faisant : Tbl.Rows[0][0] =3D "0";

et tout marche, j'ai fait pareil avec tous les autres num=E9ro de ligne, =

ca ne pose pas de prob, seulement qd je met i...

D'ailleur, si je met =E0 la place de i -1 ou, 5 (soit 1 de plus que le=20
nombre de ligne), il me dit juste qu'il n'y =E0 aucune ligne.

Merci de votre aide, pcq l=E0 je s=E8che... :(

10 réponses

1 2 3
Avatar
Vincent Lascaux
> Ca va être chaud, alors j'ai fait un test vite fait :



Pourquoi ne peux tu pas supprimer bêtement tout le code de l'interface
graphique... pour ne garder que ce qui concerne notre probleme, et le poster
ici ?

--
Vincent

PS: un indice : la réponse n'est pas "parceque j'ai pas le temps et que je
préfere que les autres perdent le leur à essayer de deviner mon probleme"
Avatar
amplitude
Ok, mais je ne sais pas si ca va servir, j'utilise un control qui
s'appel GRIDEX :

using System;
using System.Data.Odbc;
using System.Data;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using MySQLDriverCS;

namespace ampCompta.Factures
{
/// <summary>
/// Summary description for Reglement.
/// </summary>
public class Reglement : System.Windows.Forms.Form
{
#region Designer
#endregion

private decimal MontantRecu = 0;
private Hashtable HSClient;
private Hashtable HSCompte;
private System.Windows.Forms.ComboBox comboBox1;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
private DataTable Tbl;

/// <summary>
/// Rentrez une valeur vide type "" pour afficher tous les comptes
/// </summary>
public Reglement(string NumeroCompte)
{
InitializeComponent();
UpListeCompte();
UpListeClient();
}

private void UpListeFact(string CodeClient)
{
Principale.con.Open();
DataTable Tbl1 = new MySQLSelectCommand(
Principale.con,
new string[] {"DateCrea","Numero","Reference","MontantHT","MontantTVA "},
new string[] {"Factures"},
new object[,] {{"PayeeLe","=","0000-00-00"},{"Client","=",CodeCli ent}},
null,
new string[,] {{"Numero","ASC"}}).Table;
Principale.con.Close();

Tbl = new DataTable("FactNonPayees");
Tbl.Columns.Add("Date");
Tbl.Columns.Add("Numéro");
Tbl.Columns.Add("Référence");
Tbl.Columns.Add("Montant dû");
Tbl.Columns.Add("Ventilation");

foreach(DataRow r in Tbl1.Rows)
{
DataRow dt = Tbl.NewRow();
dt["Date"] = r["DateCrea"];
dt["Numéro"] = r["Numero"];
dt["Référence"] = r["Reference"];
dt["Montant dû"] =
decimal.Parse(r["MontantHT"].ToString().Replace(".",","))+decimal.Parse(r ["MontantTVA"].ToString().Replace(".",","));
dt["Ventilation"] = 0m;
Tbl.Rows.Add(dt);
}

System.Data.DataSet DS1 = new DataSet();
DS1.Tables.Add(Tbl);

this.gridEXFactures.DataMember = DS1.Tables[0].TableName;
this.gridEXFactures.DataSource = DS1;
this.gridEXFactures.RetrieveStructure();
for(int i=0;i<Tbl.Columns.Count;i++)
{
if(i!=Tbl.Columns.Count-1)
{
this.gridEXFactures.RootTable.Columns[i].EditType =
Janus.Windows.GridEX.EditType.NoEdit;
}
else
{
this.gridEXFactures.RootTable.Columns[i].EditType =
Janus.Windows.GridEX.EditType.TextBox;
this.gridEXFactures.RootTable.Columns[i].DefaultValue = "0,00";
}
}
AdjustCol();
}

private void UpListeCompte()
{
Principale.conBanque.Open();
DataTable Tbl1 = new MySQLSelectCommand(
Principale.conBanque,
new string[] {"Numero","Nom"},
new string[] {"ListeCompte"},
null,
null,
null).Table;
Principale.conBanque.Close();

HSCompte = new Hashtable();
this.comboCompte.Items.Clear();

DataTable Tbl = new DataTable("ListeCompte");
Tbl.Columns.Add("Numéro");
Tbl.Columns.Add("Nom");

int i=0;
foreach(DataRow r in Tbl1.Rows)
{
this.comboCompte.Items.Add(r["Numero"].ToString()+" -
"+r["Nom"].ToString());
HSCompte.Add(i,r["Numero"].ToString());
i++;
}
}

private void UpListeClient()
{
Principale.con.Open();
DataTable Tbl1 = new MySQLSelectCommand(
Principale.con,
new string[] {"Code"},
new string[] {"Clients"},
new object[,] {{"Type","=","CLIENT"}},
null,
new string[,] {{"Nom","ASC"}}).Table;
Principale.con.Close();

HSClient = new Hashtable();
this.comboClient.Items.Clear();

int i=0;
foreach(DataRow r in Tbl1.Rows)
{
ampCompta.Tiers.RefClient Client = new
ampCompta.Tiers.RefClient(r["Code"].ToString());
this.comboClient.Items.Add(r["Code"].ToString()+" - "+Client.Nom);
HSClient.Add(i,r["Code"].ToString());
i++;
}
}
////// interface ici normalement

private void buttonAnnul_Click(object sender, System.EventArgs e)
{
this.Close();
}


private void Reglement_Load(object sender, System.EventArgs e)
{
AdjustCol();
}

private void AdjustCol()
{
int NbCol = this.gridEXFactures.RootTable.Columns.Count-1;
this.gridEXFactures.RootTable.Columns[0].Width = 65; // Date
this.gridEXFactures.RootTable.Columns[1].Width = 60; // Numéro
this.gridEXFactures.RootTable.Columns[2].Width =
this.gridEXFactures.Width-279; // Ref
this.gridEXFactures.RootTable.Columns[3].Width = 75; // TTC
this.gridEXFactures.RootTable.Columns[4].Width = 75; // Ventilation
}

private void EnableDisable()
{
if(this.textMontant.Text.Length > 0)
{
try
{
MontantRecu = decimal.Parse(this.textMontant.Text.Replace(".",",") );
this.labelMontantRestant.Text = MontantRecu.ToString("# ### ### ## #
###.##")+" €";
}
catch
{
MessageBox.Show("La valeur ne semble pas être correct");
this.textMontant.Text = MontantRecu.ToString();
this.textMontant.Focus();
}
this.comboCompte.Enabled = true;
this.comboCompte.SelectedIndex = 0;
this.comboClient.Enabled = true;
this.comboClient.SelectedIndex = 0;
this.gridEXFactures.Enabled = true;
}
else
{
this.labelMontantRestant.Text = MontantRecu.ToString("# ### ### ###
###.##")+" €";
this.comboCompte.Enabled = false;
this.comboClient.Enabled = false;
this.gridEXFactures.Enabled = false;
this.buttonOk.Enabled = false;
}
}

private void textMontant_KeyPress(object sender,
System.Windows.Forms.KeyPressEventArgs e)
{
if(!char.IsLetter(e.KeyChar) || e.KeyChar == ',' || e.KeyChar == '.')
{
e.Handled = false;
}
else
{
e.Handled = true;
}
}

private void textMontant_TextChanged(object sender, System.EventArgs e)
{
EnableDisable();
}

private void comboClient_SelectedIndexChanged(object sender,
System.EventArgs e)
{
UpListeFact(HSClient[this.comboClient.SelectedIndex].ToString());
}

private void gridEXFactures_CellUpdated(object sender,
Janus.Windows.GridEX.ColumnActionEventArgs e)
{
Tbl.Rows[0][0] = "Test";

// decimal MontantVentile = 0;
// int i=0;
// foreach(DataRow dt in Tbl.Rows)
// {
// string txt =
this.gridEXFactures.GetRow(i).Cells[Tbl.Columns.Count-1].Text;
// if(txt.Length > 0)
// {
// MontantVentile += decimal.Parse(txt.Replace(".",","));
// dt[0] = txt.Replace(".",",");
// }
// i++;
// }
// decimal MontantRestant = MontantRecu-MontantVentile;
// if(MontantRestant == 0)
// {
// this.buttonOk.Enabled = true;
// MontantRestant = 0;
// }
// this.labelSommePaiements.Text = MontantVentile.ToString("# ### ###
### ###.##")+" €";
// this.labelMontantRestant.Text = MontantRestant.ToString("# ### ###
### ###.##")+" €";
}


La partie en commentaire juste au dessus est monde que je veux faire...



Vincent Lascaux wrote:
Ca va être chaud, alors j'ai fait un test vite fait :




Pourquoi ne peux tu pas supprimer bêtement tout le code de l'interfac e
graphique... pour ne garder que ce qui concerne notre probleme, et le p oster
ici ?



Avatar
Vincent Lascaux
> Ok, mais je ne sais pas si ca va servir, j'utilise un control qui



Est ce que l'erreur s'arrete si tu enleve n'importe quelle ligne de code ?
Est ce qu'il n'y a plus d'erreur si tu vides la fonction UpListeCompte par
exemple (au pif) ?
Si non, tu peux supprimer cette fonction, et continuer jusqu'à n'avoir plus
qu'un code minimal qu'on pourra lire rapidement sans chercher à comprendre
ce qui doit se passer pour que ta fonction qui pose probleme soit lancée et
tout...
Normalement, il faudrait que tu arrives à un code de quelques dizaines de
lignes. Génerallement on trouve l'erreur par soi même quand on fait ca

--
Vincent
Avatar
Vincent Lascaux
> Ok, mais je ne sais pas si ca va servir



Quand je disais de virer du code, je parlais de virer celui qui ne change
pas le probleme. Il me semble que tu as viré certaines lignes de code qui
sont importantes pour le probleme : la fonction qui pose probleme
(gridEXFactures_CellUpdated) est private et n'est jamais utilisée par la
classe elle même, elle ne peut donc pas etre appelée, et il ne peut donc pas
y avoir de probleme à l'execution (dans cette fonction en tous cas)

--
Vincent
Avatar
amplitude
En fait, la ligne qui pose prob est encore là, enfin, simplifier
justement, juste au dessus des commentaires :

Tbl.Rows[0][0] = "Test";

Il se bloque là dessus

Merci pour ton aide. :)


Vincent Lascaux wrote:
Ok, mais je ne sais pas si ca va servir




Quand je disais de virer du code, je parlais de virer celui qui ne chan ge
pas le probleme. Il me semble que tu as viré certaines lignes de code qui
sont importantes pour le probleme : la fonction qui pose probleme
(gridEXFactures_CellUpdated) est private et n'est jamais utilisée par la
classe elle même, elle ne peut donc pas etre appelée, et il ne peut donc pas
y avoir de probleme à l'execution (dans cette fonction en tous cas)



Avatar
amplitude
En fait, au cas où :

Ce que je fais, c que dans le control GridEx l'utilisateur rentre une
nouvelle donée (une colonne est éditable), puis je récup les donné es
rentré, et je voudrais (c'est là que ça cloche) mettre ma table à jour
avec les nouvelles données...


amplitude wrote:
En fait, la ligne qui pose prob est encore là, enfin, simplifier
justement, juste au dessus des commentaires :

Tbl.Rows[0][0] = "Test";

Il se bloque là dessus

Merci pour ton aide. :)


Vincent Lascaux wrote:

Ok, mais je ne sais pas si ca va servir





Quand je disais de virer du code, je parlais de virer celui qui ne
change pas le probleme. Il me semble que tu as viré certaines lignes
de code qui sont importantes pour le probleme : la fonction qui pose
probleme (gridEXFactures_CellUpdated) est private et n'est jamais
utilisée par la classe elle même, elle ne peut donc pas etre appel ée,
et il ne peut donc pas y avoir de probleme à l'execution (dans cette
fonction en tous cas)






Avatar
Paul Bacelar
Bon, on commence par le début ;-).

StackOverFlow, c'est un dépassement de capacité de la pile.

La pile c'est la zone mémoire qui est utilisé pour stocker les variables
automatiques.

Les variables automatiques, c'est les variables que le langages alloue
automatiquement comme les arguments du méthode que tu passe par valeur ou
les variables locale de type ValueType (in, float, double, struct, etc.).
Ces variables sont à l'opposé des variables allouées avec un new qui elle
sont stockées dans le tas (heap). Le garbage collector ne s'occupe que du
tas.

La gestion de variables automatiques se fait par empilement-dépilement.
Quand tu entres dans une méthode, la pile augmente de la taille de tes
variables automatiques (paramètres et variables locales). Quand tu sors de
la méthode, la pile diminue d'autan qu'elle a augmenté en entrant.

Donc entre l'entrée dans une méthode et sa sortie, la pile a augmenté en
taille. Mais la taille de la pile au moment de la sortie est la même qu'à
son entré dans la méthode.

C'est pareil pour tous les langages, .NET ou pas.

Alors comment une pile peut-elle grandir jusqu'à exploser l'espace qui lui
était réservé ?

J'en vois deux:

- une récursivité trop profonde, c'est à dire une méthode qui s'appel elle
même de manière direct ou indirect, ce qui entraîne une augmentation de la
pile à chaque appel qui entraînera un nouvel appel avec une nouvelle
augmentation de la pile et ainsi de suite jusqu'au dénouement fatale.

- une taille de l'ensemble des variables automatiques très importantes,
comme une structure contenant des millions de int passé par valeur à
plusieurs méthodes successivement. Cette hypothèse est peu plausible avec
les langages .NET qui utilisent énormément les références sur des objets
contrairement au C avec ses tableaux.



Tout cela ne sont que des généralités mais il faut bien être conscient de la
situation, qui est pour le moins critique et hostile.

Si mes lieux communs ont été suffisamment clairs, le fait d'appeler une
méthode comme MessageBox qui utilise des variables automatiques (au moins
pour ses paramètres) quand une StackOverFlow est lancée sera aussi saugrenue
que de faire un new pendant le traitement d'une exception de type
OutOfMemory ;-).

Si l'image te frappe, tu comprendra que tu ne verra pas de MessageBox car tu
as subis une StackOverFlowException pendant le traitement de la première
exception (c'est un throw dans un catch).

Il ne reste donc qu'a rusé pour voir le problème avant que la pile soit
pleine car après, c'est Tchernobyl dans la mémoire, même le débuggeur y perd
ses petits car le contenue de la stack a de fortes chances d'être corrompu.



Alors, petit padawan, depuis des temps qui datent de bien avant l'existence
des premiers débuggeurs, de vaillants programmeurs, seulement munis de leur
simples bibliothèques d'entrée-sortie (et même pas laser), ont mis au point
une technique ultra puissante.

C'est simplement d'afficher sur la console des traces de l'activité du
programme.

Le printf("coucou") de mon précédent post est une instruction C qui ne fait
qu'afficher "coucou" dans la console du programme à la suite des autres
affichages. Si dans la console a affiché un "coucou", c'est que nous sommes
passée une fois dans cette instruction, si il y a 2 "coucou", c'est que nous
sommes passée deux fois dans cette instruction etc...

Avec .NET, les bibliothèques d'entrées-sorties se sont perfectionnées et
"Debug.Write("coucou")" est l'instruction .NET qui va permettre d'afficher
"coucou" dans la fenêtre "Sortie" ou "Output" de VS.NET, la fenêtre qui est
généralement en bas et qui indique le chargement des assemblies.



<CODE>Debug.WriteLine(i.ToString() + " " +
Tbl.Rows.Length.ToString());</CODE>

dans ta boucle permettra de voir l'évolutions de ces valeurs avant que le
drame (l'explosion de la pile) n'arrive.



PS: Voici un exemple du pourquoi il ne faut pas catcher les exceptions quand
on n'est pas capable des les résoudre.

Ne catchez pas à tord et à travers ;-). En catchant Exception, vous pouvez
avoir une OutOfMemoryException et si vous avez pas réservé de la mémoire
pour un traitement d'urgence, vous aurez l'air fin avec votre catch.

--
Paul Bacelar

"amplitude" wrote in message
news:cl6otr$jqd$
Le c# est mon premier language de prog, donc je ne comprend pas tout...
Mais si tu parles d'un try{ } catch{] j'ai essayé avec un MessageBox qui
me retourne l'exception, mais il ne le prend pas en compte !! C'est
d'ailleur la première fois que ça me le fait !



Paul Bacelar wrote:
Quand il y a une StackOverFlow, généralement le débuggeur est aux fraises
sur la zone qui pose problème.

Le bon vieux printf("coucou") de notre glorieux passé C est encore
d'actualité.

Donc, fais des debug.Trace dans ta boucle pour voir.


Avatar
Paul Bacelar
Je crois que tu as mis le doigt dessus.

C'est du code récursif qui s'auto-appel indirectement.

Le plus simple, ne mettre à jour ta table que si la valeur change.
--
Paul Bacelar


"amplitude" wrote in message
news:cl6sd1$kt2$
En fait, au cas où :

Ce que je fais, c que dans le control GridEx l'utilisateur rentre une
nouvelle donée (une colonne est éditable), puis je récup les données
rentré, et je voudrais (c'est là que ça cloche) mettre ma table à jour
avec les nouvelles données...


amplitude wrote:
En fait, la ligne qui pose prob est encore là, enfin, simplifier
justement, juste au dessus des commentaires :

Tbl.Rows[0][0] = "Test";

Il se bloque là dessus

Merci pour ton aide. :)


Vincent Lascaux wrote:

Ok, mais je ne sais pas si ca va servir





Quand je disais de virer du code, je parlais de virer celui qui ne
change pas le probleme. Il me semble que tu as viré certaines lignes
de code qui sont importantes pour le probleme : la fonction qui pose
probleme (gridEXFactures_CellUpdated) est private et n'est jamais
utilisée par la classe elle même, elle ne peut donc pas etre appelée,
et il ne peut donc pas y avoir de probleme à l'execution (dans cette
fonction en tous cas)






Avatar
amplitude
Merci bcp pour toutes ces explications, je comprend mieux! :)

Sinon, quel est l'assembly de Debug, pcq qu'il ne le trouve pas, et moi
non plus...



Paul Bacelar wrote:
Bon, on commence par le début ;-).

StackOverFlow, c'est un dépassement de capacité de la pile.

La pile c'est la zone mémoire qui est utilisé pour stocker les vari ables
automatiques.

Les variables automatiques, c'est les variables que le langages alloue
automatiquement comme les arguments du méthode que tu passe par valeu r ou
les variables locale de type ValueType (in, float, double, struct, etc. ).
Ces variables sont à l'opposé des variables allouées avec un new qui elle
sont stockées dans le tas (heap). Le garbage collector ne s'occupe qu e du
tas.

La gestion de variables automatiques se fait par empilement-dépilemen t.
Quand tu entres dans une méthode, la pile augmente de la taille de te s
variables automatiques (paramètres et variables locales). Quand tu so rs de
la méthode, la pile diminue d'autan qu'elle a augmenté en entrant.

Donc entre l'entrée dans une méthode et sa sortie, la pile a augmen té en
taille. Mais la taille de la pile au moment de la sortie est la même qu'à
son entré dans la méthode.

C'est pareil pour tous les langages, .NET ou pas.

Alors comment une pile peut-elle grandir jusqu'à exploser l'espace qu i lui
était réservé ?

J'en vois deux:

- une récursivité trop profonde, c'est à dire une méthode qui s 'appel elle
même de manière direct ou indirect, ce qui entraîne une augmentat ion de la
pile à chaque appel qui entraînera un nouvel appel avec une nouvell e
augmentation de la pile et ainsi de suite jusqu'au dénouement fatale.

- une taille de l'ensemble des variables automatiques très importante s,
comme une structure contenant des millions de int passé par valeur à
plusieurs méthodes successivement. Cette hypothèse est peu plausibl e avec
les langages .NET qui utilisent énormément les références sur d es objets
contrairement au C avec ses tableaux.



Tout cela ne sont que des généralités mais il faut bien être co nscient de la
situation, qui est pour le moins critique et hostile.

Si mes lieux communs ont été suffisamment clairs, le fait d'appeler une
méthode comme MessageBox qui utilise des variables automatiques (au m oins
pour ses paramètres) quand une StackOverFlow est lancée sera aussi saugrenue
que de faire un new pendant le traitement d'une exception de type
OutOfMemory ;-).

Si l'image te frappe, tu comprendra que tu ne verra pas de MessageBox c ar tu
as subis une StackOverFlowException pendant le traitement de la premiè re
exception (c'est un throw dans un catch).

Il ne reste donc qu'a rusé pour voir le problème avant que la pile soit
pleine car après, c'est Tchernobyl dans la mémoire, même le déb uggeur y perd
ses petits car le contenue de la stack a de fortes chances d'être cor rompu.



Alors, petit padawan, depuis des temps qui datent de bien avant l'exist ence
des premiers débuggeurs, de vaillants programmeurs, seulement munis d e leur
simples bibliothèques d'entrée-sortie (et même pas laser), ont mi s au point
une technique ultra puissante.

C'est simplement d'afficher sur la console des traces de l'activité d u
programme.

Le printf("coucou") de mon précédent post est une instruction C qui ne fait
qu'afficher "coucou" dans la console du programme à la suite des autr es
affichages. Si dans la console a affiché un "coucou", c'est que nous sommes
passée une fois dans cette instruction, si il y a 2 "coucou", c'est q ue nous
sommes passée deux fois dans cette instruction etc...

Avec .NET, les bibliothèques d'entrées-sorties se sont perfectionné es et
"Debug.Write("coucou")" est l'instruction .NET qui va permettre d'affic her
"coucou" dans la fenêtre "Sortie" ou "Output" de VS.NET, la fenêtre qui est
généralement en bas et qui indique le chargement des assemblies.



<CODE>Debug.WriteLine(i.ToString() + " " +
Tbl.Rows.Length.ToString());</CODE>

dans ta boucle permettra de voir l'évolutions de ces valeurs avant qu e le
drame (l'explosion de la pile) n'arrive.



PS: Voici un exemple du pourquoi il ne faut pas catcher les exceptions quand
on n'est pas capable des les résoudre.

Ne catchez pas à tord et à travers ;-). En catchant Exception, vous pouvez
avoir une OutOfMemoryException et si vous avez pas réservé de la mé moire
pour un traitement d'urgence, vous aurez l'air fin avec votre catch.



Avatar
amplitude
Paul Bacelar wrote:
Je crois que tu as mis le doigt dessus.

C'est du code récursif qui s'auto-appel indirectement.

Le plus simple, ne mettre à jour ta table que si la valeur change.



c pareil :

if(dt["Ventilation"] != txt)
{
MontantVentile += decimal.Parse(txt.Replace(".",","));
dt["Ventilation"] = txt.Replace(".",",");
}

Voilà ce que j'ai fait, mais il me fait toujour sl'erreur!! :{{

Comment feriez-vous vous pour mettre à jour les données d'une table à
partir des données d'une colonne d'un dataGrid par exemple ???
1 2 3