[Code] Crash si instructions hors du loop()

Bonjour à tous,

Je suis entrain de me battre avec un problème que j'ai eu plusieurs fois et dont celui-ci c'est réglé soit par chance, soit par une incompréhension de ma part.

Ici, je suis face à ce problème encore une fois, que je n'arrive pas à résoudre.

En gros, quand je donne des instructions dans le loop(), le code fonctionne parfaitement sans erreurs ni fuite de mémoire ( testé avec memoryFree ), et ce pendant plusieurs heures. Je suppose donc qu'il n'y a pas de soucis de ce côté là.

Voulant avoir un code un peu plus propre, je me décide de retirer ces quelques instructions du loop() et de créer une fonction "connectionToDevice" faisant exactement la même chose. Bref, que du copier-coller. Or, il se fait que mon programme crash sans raison apparente. Toujours avec la libairie memoryFree, il n'y a aucun soucis de mémoire.

Le code fonctionnel est ci-dessous.

Fonctionnement de Communication :
J'attends que l'utilisateur envoie "yes" pour pouvoir démarrer une communication.
Si la communication démarre j'exécute certaines instruction ( Notamment je lui demande une "action" ), sinon non.

En gros ce qui se passe dans la console :
-J'attends qu'on m'envoie "ready", j'envoie alors "yes" -> communication
-Ensuite, j'envoie 50, je rentre dans le cas defaut du switch de actionListener
-Print des autres Serial.

void loop()
{
    Serial.print("first sec : ");
    //connectionToDevice();
    //connectionToDevice();

    char action[10] = {'\0'};
        if(com.tryCommunication())
        {
            com.sendInformations("connection");
            com.recieveInformations(action,10);
            Serial.println(action);
            actionListener(action);
            Serial.println("Crash apres action");
        }
    Serial.println("on est passe :");

    switch(counter)
    	{
    	case 0 : 
        	Serial.println("on est dans case 0");
    	default :
       		 counter = 0;
    	}
}

Sachant que "counter" est une variable global

La classe Communication :

#include "Communication/Communication.h"
#define TIME_MAX_WAIT_COMM  4// in seconds
#define MAX_LENGTH_INFO 10
Communication::Communication()
{
}
bool Communication::tryCommunication()
{
    Serial.println(F("ready?"));
    delay(100);
    char test[MAX_LENGTH_INFO]= {'\0'};
    if(!recieveInformations(test,MAX_LENGTH_INFO))
        return false;
    if(strcmp(test,"yes")==0)
    {
        return true;
    }
    return false;
}

bool Communication::recieveInformations(char tab[], byte lenghtTab)
{
    byte mill = 0;
    byte i;
    while(!(Serial.available()>0) && ((mill)<TIME_MAX_WAIT_COMM))
    {
        delay(1000);
        mill++;
    }
     for( i=0; i<lenghtTab; i++) // on initialise
    {
        tab[i] = '\0';
    }
    for( i=0; Serial.available()>0 && i<lenghtTab; i++)
    {
        tab[i] = Serial.read();
    }
    if(i==0)
        return false;
    else
        return true;

}
void Communication::sendInformations(String toSend)
{
    Serial.println(toSend);
}

La fonction actionListener

void actionListener(char event[])
{
    Serial.println(event);
    byte action = atol(event);
    char line[50] = {'\0'};
    char fileName[10] = {'\0'};
    long secLight;
    switch(action)
    {
    case WRITE_AND_DELETE :
         // code inutile
        break;
    case PLAY_24_HOURS_LIGHTS :
        //code inutile
        break;
    case WRITE_END_OF_FILE :
        // code inutile
        break;
    default :
        Serial.println("envoye yes !");
        Serial.print("freeMemory()=");
        Serial.println(freeMemory());
        com.sendError(100);
        break;
    }
    delay(1000);
    Serial.println("Ccrash actionListener");
}

Code non fonctionnel :

void connectionToDevice();
void loop()
{
    Serial.print("first sec : ");
    connectionToDevice();
    connectionToDevice();
    Serial.println("on est passe :");

    switch(counter)
    	{
    	case 0 : 
        	Serial.println("on est dans case 0");
    	default :
       		 counter = 0;
    	}
}

void connectionToDevice()
{ char action[10] = {'\0'};

        if(com.tryCommunication())
        {
            com.sendInformations("connection");
            com.recieveInformations(action,10);
            Serial.println(action);
            actionListener(action);
            Serial.println("Crash apres action");
        }
}

Le crash se passe aléatoirement après connectionToDevice quand on exécute ( et uniquement ) actionListener.

J'obtiens en effet dans la console soit :
-Crash apr (puis tout des chiffres bizarres)

  • On est dan ( et tout des chiffres bizarres encore...)

Que peut-il bien se passer ?
Si mes explications ne sont pas claires, n'hésitez surtout pas à me demander des informations :).

Merci à tous

Bonjour,

J'ai déjà fait un test comme celui-ci et le problème reste le même. Malgré la faute que vous avez relevée :).

En fait, j'instancie tout le tableau à '\0' et je n'envoie des nombres que de 3 caractères ( donc max 999).
Dès lors, il me restait 10-3-1 = 6 places libres à '\0'.

Je suis bien d'accord pour votre NB, mais si j'utilise le code dans les même conditions ( j'envoie exactement la même chose dans un même intervalle de temps), pourquoi le retirer de la fonction "loop()" ferait-il tout crasher ?

Il y a une logique que je ne comprends malheureusement pas.

Merci

Bonjour,

C'est le cas classique quand on écrit à l'extérieur d'un tableau (je ne veux pas dire que ce soit ça ton problème). Quelquefois ça fonctionne (parce que la mémoire est inutilisée), quelquefois ça ne fonctionne pas et quelquefois ça crashe complètement. Ca dépend ou ton programme écrit.
Ca semble fonctionner, tu ajoutes, enlève ou déplace une variable et ça crashe complètement.

Hum, d'accord. Il se peut donc très bien que ce soit une faute dans le reste de mon code malheureusement :/.

Avez-vous une technique rapide pour détecter une telle erreur ? J'ai quand même 1560 lignes de code ainsi que plusieurs librairies utilisées. Ce qui va me prendre sûrement beaucoup de temps.

Merci à vous deux,

EDIT :
Si je supprime ( commente ) les fonctions que je n'utilise pas et que je debug ainsi. Dès que le crash ne se passe plus, je peux en conclure que le problème viendrait de la dernière fonction commentée non ?
EDIT 2 :
Les seules fonction qui seraient associée à un problème pareil sont bien les fonctions qui utilisent un tableau n'est ce pas ? Surtout si elles travaillent sur un tableau passé en argument ?

bonjour

    for( i=0; Serial.available()>0 && i<lenghtTab; i++)
    {
        tab[i] = Serial.read();
    }
    if(i==0)
        return false;
    else
        return true;

2 problèmes ici

  1. Ton for ne devrais pas aller jusque "i< lenghtTab" mais jusque "i< lenghtTab -1" pour laisser la place pour la terminaison (le 0 de fin)
  2. Si ta réception n'est pas complètement arrivée, la condition du for va faire sortir de la boucle car Serial.available()>0 sera fausse.
    Pour être sur d'avoir tes 3 octets, test si tu as reçu 3 octets
    while(!(Serial.available()>=3) && ((mill)<TIME_MAX_WAIT_COMM))
    {
        delay(1000);
        mill++;
    }

a+

Bonjour,
Problème réglé pour cette fonction ( comme pepe l'avait aussi souligné).

Quand on parle du 0 de fin, on peut l'écrire ainsi :
char zeroDeFin ='\0' ;
N'est ce pas ?

Deuxième chose, j'ai bel et bien un soucis. Voici un print de la console dans ma fonction readSettings. Celle-ci est peut être problématique, mais je ne trouve pas :/.

Type any character to start
temp 1 2 (*)

freeMemory()=192
ph 5 (*)

freeMemory()=192
light 6 103 1 (*)

freeMemory()=192
white warm find
light 9 104 1 (*)

freeMemory()=192
white cold find et pin 
light 5 101 1 (*)

freeMemory()=192
blue find
light 10 100 1 (*)

freeMemory()=192 
Red find
lighton 60000 30000 0 36000 42000 (*)

freeMemory()=192
lightof 77000 40000 0 65000 60000 (*)

freeMemory()=192
lightfu 1 1 1 1 1 (*)

freeMemory()=192


freeMemory()=192
NOT FOUND SETTINGS
Doit on updater ?0
Device ready
temp 1 2 (*)

freeMemory()=-8859
ph 5 (*)

freeMemory()=-8859
light 6 103 1 (*)

freeMemory()=-8859
white warm find
light 9 104 1 (*)

freeMemory()=-9627
white cold find et pin 
light 5 101 1 (*)

freeMemory()=-9627
blue find
light 10 100 1 (*)

freeMemory()=-8859
Red find
lighton 60000 30000 0 36000 42000 (*)

freeMemory()=-9627
lightof 77000 40000 0 65000 60000 (*)

freeMemory()=-8859
lightfu 1 1 1 1 1 (*)

freeMemory()=-8859


freeMemory()=-9627
NOT FOUND SETTINGS
Doit on updater ?0

Je suppose que des nombres négatifs ne valent rien de bon.
Les lignes où j'ai ajouté (*) sont lues de la carte SD.

Voici la fonction readSettings, y voyez-vous une erreur ?
Le fonctionnement est le suivant :
Je lis une seule ligne.
Je l'envoie ensuite à lineToTab pour remplir un tableau avec ce qui est écrit dans la ligne envoyé. ( Je complète donc des données dans un tableau)

Je précise que je ne déborde jamais la taille des tableaux :slight_smile: ( c'est moi qui le fait et je sais ce que j'envoie. Evidemment, si j'ai envie de faire péter le bazar, c'est possible et c'est peut être ce qui se passe :confused: )

void readSettings()
{
    bool update;
    bool trueUpdate = false;
    char buffer[MAX_BUFFER];

    byte j=0;
    while (readFileLine("SETTINGS.TXT",j,buffer,MAX_BUFFER))
    {
        char a[MAX_INFORMATION][MAX_INFORMATION_LETTERS]= {'\0'};
        Serial.println(buffer);
        delay(200);
        j++;
        lineToTab(buffer,&a[0][0],MAX_INFORMATION,MAX_INFORMATION_LETTERS);
        //Send the informations
        update = init(a);
        if(update) trueUpdate = update;
    }

    Serial.print(F("Doit on updater ?"));
    Serial.println(trueUpdate);
    delay(100);
    // close the file:
    // data have change, must reset the device
    if(trueUpdate) software_Reset();
    while (Serial.read() <= 0) {}
}

Et les fonctions associées :

bool readFileLine(char fileName[],byte line, char *myData, byte lengthData)
{
    bool hasBreak = false;
    myFile.close(); // if some files open, close them.
    if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
    // pen the file for reading:
    if (!myFile.open(fileName, O_READ))
    {
        sd.errorHalt("opening for read failed");
    }
    byte counter = 0;
    int data;
    byte j = 0;
    char another[MAX_BUFFER] = {'\0'};
    if(MAX_BUFFER >= lengthData)
    {
        while ((data = myFile.read()) >= 0 )
        {

            another[j] = data;
            j++;
            if(data=='\n')
            {
                if( line == counter)
                {
                    hasBreak = true;
                    break;
                }
                counter++;
                j=0;
                for(int k=0; k<MAX_BUFFER; k++)
                    another[k]='\0';
            }
        }
        if(!hasBreak)
            return false;
        for(j = 0; j<lengthData; j++)
        {
            myData[j] = another[j];
        }
        return true;
    }
    else
        return false;
    // close the file:
    myFile.close();
}
bool lineToTab(char *line, char *tabToFill, byte lengthLineTab, byte lenghtColTab)//ok
{
        Serial.print("freeMemory()=");
        Serial.println(freeMemory());
    int k=0;
    //Fill buffer array
    k=0;
    for(int b=0; b<lengthLineTab; b++)
    {
        for(int i=0; line[k]!=(' ') && line[k]!=('\0') && i<lenghtColTab ; i++)
        {
            tabToFill[b*lenghtColTab + i] = line[k];
            k++;
        }
        k++;
    }
}

]

Désolé pour le nom des fonctions, j'ai jamais eu beaucoup d'idées :confused:

Merci à tous,

La fonction init(), qui ne me paraît pas très importante ici :

bool init(char tab[MAX_INFORMATION][MAX_INFORMATION_LETTERS])
{
    bool update = false;
    byte pin = atol(tab[1]);

    if(strcmp(tab[0],"temp")==0) // FCT WATER
    {
        byte number =  (byte) atol(tab[2]);
        if(EEPROM.readByte(ADRESS_PIN_TEMP_WATER) != pin)
        {
            EEPROM.writeByte(ADRESS_PIN_TEMP_WATER,pin);
            update = true;
        }
        if(EEPROM.readByte(ADRESS_NUMBER_TEMP_WATER) != number)
        {
            EEPROM.writeByte(ADRESS_NUMBER_TEMP_WATER, number);
            update = true;
        }
        return update;
    }
    if(strcmp(tab[0],"light")==0)
    {
        byte color =   atol(tab[2]);
        byte dim = atol(tab[3]);
        switch(color)// because tab[2] refer to the color
        {
        case COLOR_RED :
            Serial.println(F("Red find"));
            if(EEPROM.readByte(COLOR_RED_ADRESS_PIN) != pin)
            {
                update = true;
                EEPROM.writeByte(COLOR_RED_ADRESS_PIN,pin);
            }
            if(EEPROM.readByte(COLOR_RED_ADRESS_PIN+1) != dim)
            {
                update = true;
                EEPROM.writeByte(COLOR_RED_ADRESS_PIN+1,dim);
            }
            return update;
        case COLOR_BLUE :
            Serial.println(F("blue find"));
            if(EEPROM.readByte(COLOR_BLUE_ADRESS_PIN) != pin)
            {
                update = true;
                EEPROM.writeByte(COLOR_BLUE_ADRESS_PIN,pin);
            }
            if(EEPROM.readByte(COLOR_BLUE_ADRESS_PIN+1) != dim)
            {
                update = true;
                EEPROM.writeByte(COLOR_BLUE_ADRESS_PIN+1,dim);
            }
            return update;
        case COLOR_GREEN :
            Serial.println(F("green find"));
            if(EEPROM.readByte(COLOR_GREEN_ADRESS_PIN) != pin)
            {
                update = true;
                EEPROM.writeByte(COLOR_GREEN_ADRESS_PIN,pin);
            }
            if(EEPROM.readByte(COLOR_GREEN_ADRESS_PIN+1) != dim)
            {
                update = true;
                EEPROM.writeByte(COLOR_GREEN_ADRESS_PIN+1,dim);
            }
            return update;
        case COLOR_WHITE_WARM :
            Serial.println(F("white warm find"));
            if(EEPROM.readByte(COLOR_WHITE_WARM_ADRESS_PIN) != pin)
            {
                update = true;
                EEPROM.writeByte(COLOR_WHITE_WARM_ADRESS_PIN,pin);
            }
            if(EEPROM.readByte(COLOR_WHITE_WARM_ADRESS_PIN+1) != dim)
            {
                update = true;
                EEPROM.writeByte(COLOR_WHITE_WARM_ADRESS_PIN+1,dim);
            }
            return update;
        case COLOR_WHITE_COLD :
            Serial.println(F("white cold find et pin "));
            if(EEPROM.readByte(COLOR_WHITE_COLD_ADRESS_PIN) != pin)
            {
                update = true;
                EEPROM.writeByte(COLOR_WHITE_COLD_ADRESS_PIN,pin);
            }
            if(EEPROM.readByte(COLOR_WHITE_COLD_ADRESS_PIN+1) != dim)
            {
                update = true;
                EEPROM.writeByte(COLOR_WHITE_COLD_ADRESS_PIN+1,dim);
            }
            return update;
        }

    }
    if(strcmp(tab[0],"CO2")==0)
    {
        if(EEPROM.readByte(CO2_ADRESS_PIN) != pin)
        {
            update = true;
            EEPROM.writeByte(CO2_ADRESS_PIN,pin);
        }
        return update;
    }
    if(strcmp(tab[0],"pump")==0)
    {
        if(EEPROM.readByte(PUMP_ADRESS_PIN) != pin)
        {
            update = true;
            EEPROM.writeByte(PUMP_ADRESS_PIN,pin);
        }
        return update;
    }
    if(strcmp(tab[0],"lighton")==0 || strcmp(tab[0],"LIGHTON")==0)
    {
        //RED/BLUE/GREEN/WHITE WARM/WHITE COLD
        byte toArriveOnBIs = 0;
        if (strcmp(tab[0],"LIGHTON"))
        {
            toArriveOnBIs = 54; // please see "Definition de l'occupation de l'EEPROM"
        }
        long time = atol(tab[1]);
        if(EEPROM.readLong(COLOR_RED_ADRESS_LIGHT_ON+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_RED_ADRESS_LIGHT_ON+toArriveOnBIs,time);
        }
        time = atol(tab[2]);
        if(EEPROM.readLong(COLOR_BLUE_ADRESS_LIGHT_ON+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_BLUE_ADRESS_LIGHT_ON+toArriveOnBIs,time);
        }
        time = atol(tab[3]);
        if(EEPROM.readLong(COLOR_GREEN_ADRESS_LIGHT_ON+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_GREEN_ADRESS_LIGHT_ON+toArriveOnBIs,time);
        }
        time = atol(tab[4]);
        if(EEPROM.readLong(COLOR_WHITE_WARM_ADRESS_LIGHT_ON+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_WHITE_WARM_ADRESS_LIGHT_ON+toArriveOnBIs,time);
        }
        time = atol(tab[5]);
        if(EEPROM.readLong(COLOR_WHITE_COLD_ADRESS_LIGHT_ON+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_WHITE_COLD_ADRESS_LIGHT_ON+toArriveOnBIs,time);
        }
        return update;
    }
    if(strcmp(tab[0],"lightof")==0 || strcmp(tab[0],"LIGHTOF")==0 ) // LIGHTOFF
    {
        //RED/BLUE/GREEN/WHITE WARM/WHITE COLD
        byte toArriveOnBIs = 0;
        if (strcmp(tab[0],"LIGHTOF"))
        {
            toArriveOnBIs = 54; // please see "Definition de l'occupation de l'EEPROM"
        }
        long time = atol(tab[1]);
        if(EEPROM.readLong(COLOR_RED_ADRESS_LIGHT_OFF+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_RED_ADRESS_LIGHT_OFF+toArriveOnBIs,time);
        }
        time = atol(tab[2]);
        if(EEPROM.readLong(COLOR_BLUE_ADRESS_LIGHT_OFF+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_BLUE_ADRESS_LIGHT_OFF+toArriveOnBIs,time);
        }
        time = atol(tab[3]);
        if(EEPROM.readLong(COLOR_GREEN_ADRESS_LIGHT_OFF+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_GREEN_ADRESS_LIGHT_OFF+toArriveOnBIs,time);
        }
        time = atol(tab[4]);
        if(EEPROM.readLong(COLOR_WHITE_WARM_ADRESS_LIGHT_OFF+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_WHITE_WARM_ADRESS_LIGHT_OFF+toArriveOnBIs,time);
        }
        time = atol(tab[5]);
        if(EEPROM.readLong(COLOR_WHITE_COLD_ADRESS_LIGHT_OFF+toArriveOnBIs) != time)
        {
            update = true;
            EEPROM.writeLong(COLOR_WHITE_COLD_ADRESS_LIGHT_OFF+toArriveOnBIs,time);
        }
        return update;
    }
    if(strcmp(tab[0],"lightfu")==0) // LIGHTFUNCTION
    {
        //RED/BLUE/GREEN/WHITE WARM/WHITE COLD
        byte func = atol(tab[1]);
        if(EEPROM.readByte(COLOR_RED_ADRESS_FUNCTION) != func)
        {
            update = true;
            EEPROM.writeLong(COLOR_RED_ADRESS_FUNCTION,func);
        }
        func = atol(tab[2]);
        if(EEPROM.readByte(COLOR_BLUE_ADRESS_FUNCTION) != func)
        {
            update = true;
            EEPROM.writeLong(COLOR_BLUE_ADRESS_FUNCTION,func);
        }
        func = atol(tab[3]);
        if(EEPROM.readByte(COLOR_GREEN_ADRESS_FUNCTION) != func)
        {
            update = true;
            EEPROM.writeLong(COLOR_GREEN_ADRESS_FUNCTION,func);
        }
        func = atol(tab[4]);
        if(EEPROM.readByte(COLOR_WHITE_WARM_ADRESS_FUNCTION) != func)
        {
            update = true;
            EEPROM.writeLong(COLOR_WHITE_WARM_ADRESS_FUNCTION,func);
        }
        func = atol(tab[5]);
        if(EEPROM.readByte(COLOR_WHITE_COLD_ADRESS_FUNCTION) != func)
        {
            update = true;
            EEPROM.writeLong(COLOR_WHITE_COLD_ADRESS_FUNCTION,func);
        }
        return update;
    }
    if(strcmp(tab[0],"ph")==0)
    {
        if(EEPROM.readByte(PH_ADRESS_PIN) != pin)
        {
            update = true;
            EEPROM.writeByte(PH_ADRESS_PIN,pin);
        }
        return update;
    }
    else
        Serial.println(F("NOT FOUND SETTINGS"));
    return false;
}[/code

EDIT :
Je continue ma recherche et je pense avoir trouvé le fautif.
Je défini :
#define MAX_INFORMATION 7
#define MAX_INFORMATION_LETTERS 8

Or si je passe MAX_INFORMATION_LETTERS à 9 alors tout plante d'un seul coup. Le soucis provient bien de là ( FreeMemory s'envole à partir de ce moment).
Il n'y a plus qu'à essayer de trouver la faute ...

Bonsoir,
Je continue mes recherches. D'après moi, le problème viendrait de lineToTab et les pointeurs associés.

Mon code est maintenant fonctionnel ( mais pour combien de temps ? Ais-je résolu ce problème encore par hasard ? Est ce que j'ai encore du leak quelque part dans mon code ? ) avec le nouveau code ci-dessous.

Quelqu'un pourrait-il vérifier que ce que je fais est correct ?
Je voulais à tout prix ne pas passer par du malloc sur l'arduino.

J'avais lu quelque part que ça éparpillait la heap et que c'était très mauvais. Qu'en est-il de cette "vérité" ?

Encore une question pour faire joli,
Est-il possible de résoudre le même problème sans faire de malloc ?

Merci à tous !

bool lineToTab(char *line, char **tabToFill, byte lengthLineTab, byte lenghtColTab)//ok
{
    Serial.print("freeMemory()=");
    Serial.println(freeMemory());
    int k=0;
    //Fill buffer array
    for(int b=0; b<lengthLineTab; b++)
    {
        for(int i=0; line[k]!=(' ') && line[k]!=('\0') && i<(lenghtColTab-1) ; i++)
        {
            //tabToFill[b*lenghtColTab + i] = line[k];
            tabToFill[b][i] = line[k];
            k++;
        }
        k++;
    }
}
void readSettings()
{
    bool update=false;
    bool trueUpdate = false;
    char buffer[MAX_BUFFER];
    char** tab;
    tab = (char**) malloc(sizeof(char*)*MAX_INFORMATION);

    for(int i=0;i<MAX_INFORMATION;i++)
        *(tab+i) = (char*) malloc(sizeof(char)*MAX_INFORMATION_LETTERS);


    byte j=0;
    while (readFileLine("SETTINGS.TXT",j,buffer,MAX_BUFFER))
    {
        Serial.println(buffer);
        delay(200);
        j++;
        lineToTab(buffer,tab,MAX_INFORMATION,MAX_INFORMATION_LETTERS);
        //Send the informations
        update = init(a);

        if(update) trueUpdate = update;
    }

    for(int i=0;i<MAX_INFORMATION;i++)free(tab[i]);
        free(tab);

    Serial.print(F("Doit on updater ?"));
    Serial.println(trueUpdate);
    delay(100);
    // close the file:
    // data have change, must reset the device
    if(trueUpdate) software_Reset();
    while (Serial.read() <= 0) {}
}

bool readFileLine(char fileName[],byte line, char *myData, byte lengthData)
{
    bool hasBreak = false;
    if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
    // pen the file for reading:
    if (!myFile.open(fileName, O_READ))
    {
        sd.errorHalt("opening for read failed");
    }
    byte counter = 0;
    int data;
    byte j = 0;
    char another[MAX_BUFFER] = {'\0'};
    if(MAX_BUFFER >= lengthData)
    {
        while ((data = myFile.read()) >= 0 )
        {

            another[j] = data;
            j++;
            if(data=='\n')
            {
                if( line == counter)
                {
                    hasBreak = true;
                    break;
                }
                counter++;
                j=0;
                for(int k=0; k<MAX_BUFFER; k++)
                    another[k]='\0';
            }
        }
        if(!hasBreak)
        {
            myFile.close();
            return false;
        }
        for(j = 0; j<lengthData; j++)
        {
            myData[j] = another[j];
        }
        myFile.close();
        return true;
    }
    else
        myFile.close();
    return false;
    // close the file:
}
char** tab;
    tab = (char**) malloc(sizeof(char*)*MAX_INFORMATION);

    for(int i=0;i<MAX_INFORMATION;i++)
        *(tab+i) = (char*) malloc(sizeof(char)*MAX_INFORMATION_LETTERS);

Pourquoi ne pas définir tout simplement un tableau à 2 dimensions?

char tab[MAX_INFORMATION][MAX_INFORMATION_LETTERS]

Justement, avec le tableau à deux dimensions :

char tab[MAX_INFORMATION][MAX_INFORMATION_LETTERS]

Je n'arrivais pas à le passer à une fonction pour qu'il soit modifié.
En l’occurrence celle-ci

bool lineToTab(char *line, char **tabToFill, byte lengthLineTab, byte lenghtColTab)

Comment créer un double pointeur sur le tableau ? J'ai essayé quelque trucs mais je n'y suis pas arrivé. Internet ne m'a pas aidé beaucoup non plus. La solution que j'ai trouvé est de faire un malloc.

bonjour
Une idée mais je ne sais pas si ça fonctionne comme ça

bool lineToTab(char *line, char tabToFill[][], byte lengthLineTab, byte lenghtColTab)

J'ai encore beaucoup de mal avec les pointeurs.

a+

Pour passer un tableau à 2 dimensions en argument, il faut à minima que la première dimension soit définie. Sinon la fonction ne sait pas le manipuler.

En fait je ne comprends pas pourquoi tu ne veux pas spécifier la taille du tableau dans la déclaration de la fonction au lieu de passer sa taille en argument.

renaudyes:
Comment créer un double pointeur sur le tableau ? J'ai essayé quelque trucs mais je n'y suis pas arrivé. Internet ne m'a pas aidé beaucoup non plus. La solution que j'ai trouvé est de faire un malloc.

Si les dimensions de ton tableau sont constantes tu fais de la même façon que pour ta fonction init

bool lineToTab(char tabToFill[MAX_INFORMATION][MAX_INFORMATION_LETTERS])
{
   // ... traitement
   return true;
}

Pour l'appel
lineToTab(tab);

C'est ce que j'avais fait auparavant.

Je désespère, le problème est toujours présent quand je rajoute du code bidon dans le programme :/.
Je n'ai toujours pas résolu le soucis.

Je sais même pas, si en recommençant carrément le truc je ne ferais pas la même erreur :(.

Impossible de faire du débug sur arduino ? Comment puis-je savoir où se situe cette sal@@@ie de leak ?

EDIT :
Je deviens complètement fou. Je pense que SDFat ne peut pas avoir de problème... Et pourtant mon soucis viendrait de ça.

Pour peu que vous avez

Vous pouvez faire fonctionner le code ci-dessous qui crash :

Tout les Strings créé ont été écrit pour prendre le plus possible de place en mémoire SRAM expressément.

Ce que la console m'indique :
( Et on voit bien qu'il me reste suffisamment de RAM libre (163 voir 105) pour que normalement ça ne plante pas. Où est le soucis ? :cry: ?)

Starting device, please wait
Type any character to start
freeMemory()=163
163
freeM105Starting device, please wait
Type any character to start
freeMemory()=163
163
freeM105
Starting device, please wait
Type any character to start
freeMemory()=163
163
#include <Libraries/MemoryFree-master/MemoryFree.h>
#include <libraries/SdFat/SdFat.h>
#include <avr/pgmspace.h>
#include <Arduino.h>


void readSettings();
bool readFileLine(char fileName[],byte line, char *myData, byte lengthData);


const int chipSelect = 4;
SdFat sd;
SdFile myFile;

String str = "12345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910";
String str2 = "12345678910123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910";
String str3 = "101234567891012345678910123456789101234567891012345678910";
String str4 = "1012345678910123456789101";
String str5 = "1012345678910123456789102";
String str6 = "1012345678910123456789103";
String str7 = "1012345678910123456789104";
String str8 = "1012345678910123456789105";
String str9 = "1012345678910123456789106";
String str10 = "1012345678910123456789107dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
String str11 = "10123456789101234567891067";
String str12 = "123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789101";
String str13 = "123456789101234567891012345678910123456789101234567891012345678910123456789101234567891012345678910123456789102";
String str14 = "1230123456789101234567894567891033333333333333333333333333333333333333333333333333333321";
String str145 = "1230123456789101234567894567891033333333333333333333333333333333333333333333333333333321";
String str1455 = "1230123456789101234567894567891033333333333333333333333333333333333333333333333333333321";
String strdd = "12345678910123456789101234567891012345678910d123456789101234567891012345678910123456789101234567891012345678910";
String str2ddd = "12345678910123456fffffffffqdfqdsf9101237d89101234567910";

unsigned long sec=0;
unsigned long timeOfProgramm = 0;
unsigned long differenceTime = 0;
//char action[10] = {'\0'};
byte counter = 0;
byte counterTemp = 0;
byte mAlert[20] = {'255'};

int freeRam ()
{
    extern int __heap_start, *__brkval;
    int v;
    return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
void setup()
{
    Serial.begin(9600);
    Serial.println(F("Starting device, please wait"));
    if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
    Serial.println(F("Type any character to start"));
    Serial.print("freeMemory()=");
    Serial.println(freeMemory());
    Serial.println(freeRam());
    while (Serial.read() <= 0) {}
    readSettings();
    Serial.println(F("Device ready"));

}
void loop()
{
}


void readSettings()
{
    int MAX_BUFFER = 50;
    bool update=false;
    bool trueUpdate = false;
    char buffer[MAX_BUFFER];

    Serial.print("freeM");
    Serial.println(freeMemory());
    Serial.println(freeRam());
    byte j=0;
    readFileLine("TEST.TXT",j,buffer,(MAX_BUFFER-1));
    Serial.print(F("Doit on updater ?"));
    Serial.println(trueUpdate);
    delay(100);
    // close the file:
    // data have change, must reset the device
    while (Serial.read() <= 0) {}
}



bool readFileLine(char fileName[],byte line, char *myData, byte lengthData)
{
    bool hasBreak = false;
    Serial.println("1");
    Serial.print("freeMe=");
    Serial.println(freeMemory());
    Serial.println(freeRam());
    // pen the file for reading:
    Serial.println("1");
    if (!myFile.open(fileName, O_READ))
    {
        sd.errorHalt("opening for read failed");
    }
    int data;
    int MAX_BUFFER = 50;
    char another[50] = {'\0'};
    if(MAX_BUFFER >= lengthData)
    {
        while ((data = myFile.read()) >= 0) Serial.write(data);
    }
    // close the file:
    myFile.close();
    // close the file:
}

Dans setup, il te reste 163 octets.
Tu appelles readSettings qui déclare des variables locales (dont un tableau de 50 octets).
readSettings appelle readFileLine qui déclare des variables locales (dont un tableau de 50 octets).
Je pense très sincèrement que tu exploses la pile.

Ha, c'est bien possible en fait ... Je pensais que garder 150 bytes de réserve était suffisant sur le sketch. Peut être que la librairie ( et donc fonctions associées) demande plus de 100 bytes pour fonctionner.

Je vais donc passer sur un méga et je vous tiens au courant,

Merci pour l'aide apportée.