1

Téma: Problém s voláním funkcí dns_resolv, http_get

Dobrý den,

mám problém s funkcemi dns_resolv a http_get.

Když je zavolám v samostatném programu, který nedělá nic jiného, než že komunikuje se serverem pomocí HTTP GET požadavků, tak vše běží ok. Když ale tyto funkce použiji v programu, který je náročnější, tak mi nezbývá paměť a konzole vypíše:

*** FULL-C ***: out of mem(29)(72)(H)
*** FULL-C ***: out of mem(30)
*** FULL-C ***: out of mem(20)

Celý program zabírá 18 kB (28% paměti), stack zabírá 5% a na heap zbývá 67%.

Když odstraním z programu 7 globálních int polí, každé o 64 indexech, tak to beží.

Je možné, že výše zmíněné funkce jsou na paměť tak náročné? Nebo dělám něco špatně?

Předem díky za odpovědi,
Jakub

2

Re: Problém s voláním funkcí dns_resolv, http_get

Prosím napište sem kus kódu vašeho programu, kde jsou ty globální pole definovány. Přesně celý kód kolem těch definic atd.

Zkuste zvětšit stack. I když, chyba dle popisu chybové hlášky, odpovídá tomu, že došla pamět na HEAPu, při vstupu do funkce. Nepředáváte ty pole do nějaké vaší funkce, nějak "špatně" ? Tj. bez použití ukazatele na pole ? atd.
Zkuste sem dát části vašeho kódu, kde se s tím vším pracuje.

Ono to nemusí být ani chyba způsobená použitím těch sedmin polí, ty jen mohly být "poslední kapka" a paměť došla, a už předtím tam mohl být nějaký jiný, původní problém v programu. Neprovádíte tam např. příliš hlubokou rekurzi ? Nepředáváte proměnné (velké pole) do funkce přímo (správně by to mělo být přes ukazatel)? atd.
Jednoznačně se vyčerpá stack / heap.
V průběhu běhu programu můžete kontrolovat hodnoty využití (za běhu, na web admin "full-c" ve vašem SDS). Zkuste se podívat, jestli program už není na kraji vyčerpání zdrojů...

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

3

Re: Problém s voláním funkcí dns_resolv, http_get

Zvětšil jsem STACK z 3072 na 4096, ale stále mi to hlásí nedostatek paměti.

Definice globálních polí:

// Pole pro ukládání naměřených hodnot ze senzorů
char addrArray[264]; // min 264 kvůli zapisování do DataFlash
char typeArray[264];
int tempArray[64]; // max 64 senzorů kvůli nedostatku paměti
int humArray[64];
int moiArray[64];
int resiArrayHI[64]; // do unsigned int pole ve full-c se na jeden index vejde pouze 16 bitů -> je potřeba 32 bitovou hodnotu rozdělit do dvou indexů
int resiArrayLO[64];
int temp2Array[64];
int hum2Array[64];

Pokud odstraním poslední tři pole, tak program běží. Pokud zmenším počet indexů v každém poli na 32, tak se vůbec nerozběhne a hned dává chybovou hlášku out of mem.

S těmito poli pracuji v této části programu:

// Naplní příslušná pole naměřenými hodnotami ze senzorů.
void readSensors() {
    if(sensorCount == 0) {
        printf("No sensors connected...\n");
        break;
    }
    for(int i = 0; i < sensorCount; i++) {
        sensorAddr = addrArray[i];
        if(typeArray[i] == TYPE_HT) {
            printf("Reading sensor address %d, sensor type %d...\n", sensorAddr, TYPE_HT);
            if (readValues(3) == 0) { // register count 3
                tempArray[i] = 0;
                humArray[i] = 0;
                moiArray[i] = 0;
                resiArrayHI[i] = 0;
                resiArrayLO[i] = 0;
                temp2Array[i] = 0;
                hum2Array[i] = 0;
            }
            else {
                tempArray[i] = ((res[3] << 8) | res[4]);
                humArray[i] = ((res[5] << 8) | res[6]);
                moiArray[i] = 0;
                resiArrayHI[i] = 0;
                resiArrayLO[i] = 0;
                temp2Array[i] = 0;
                hum2Array[i] = 0;
            }
        }
        if(typeArray[i] == TYPE_MHT_22) {
            printf("Reading sensor address %d, sensor type %d...\n", sensorAddr, TYPE_MHT_22);
            if (readValues(6) == 0) { // register count 6
                tempArray[i] = 0;
                humArray[i] = 0;
                moiArray[i] = 0;
                resiArrayHI[i] = 0;
                resiArrayLO[i] = 0;
                temp2Array[i] = 0;
                hum2Array[i] = 0;
            }
            else {
                tempArray[i] = ((res[3] << 8) | res[4]);
                humArray[i] = ((res[5] << 8) | res[6]);
                moiArray[i] = ((res[9] << 8) | res[10]);
                resiArrayHI[i] = ((res[11] << 8) | res[12]);
                resiArrayLO[i] = ((res[13] << 8) | res[14]);
                temp2Array[i] = 0;
                hum2Array[i] = 0;
            }
        }
        if(typeArray[i] == TYPE_MHT_23) {
            printf("Reading sensor address %d, sensor type %d...\n", sensorAddr, TYPE_MHT_23);
            if (readValues(12) == 0) { // register count 12
                tempArray[i] = 0;
                humArray[i] = 0;
                moiArray[i] = 0;
                resiArrayHI[i] = 0;
                resiArrayLO[i] = 0;
                temp2Array[i] = 0;
                hum2Array[i] = 0;
            }
            else {
                tempArray[i] = ((res[3] << 8) | res[4]);
                humArray[i] = ((res[5] << 8) | res[6]);
                moiArray[i] = ((res[9] << 8) | res[10]);
                resiArrayHI[i] = ((res[11] << 8) | res[12]);
                resiArrayLO[i] = ((res[13] << 8) | res[14]);
                temp2Array[i] = ((res[23] << 8) | res[24]);
                hum2Array[i] = ((res[25] << 8) | res[26]);
            }
        }
    }
}

Vyčítám hodnoty ze senzorů připojených přes RS485 a každou odpověď zapisuji nejprve do pole res[].

Pro zobrazení hodnot na webové stránce používám tuto část kódu:

// Naplní pole T00 až T07 hodnotami z polí s naměřenými hodnotami.
void sendDataToWebPage() {
    int index = 0;

    for (int i = 0; i < sensorCount; i++) {
        if (i < sensorCount - 1) {
            index += snprintf(&T00[index], 3, "%d,", addrArray[i]) - 1;
        }
        else {
            index += snprintf(&T00[index], 3, "%d", addrArray[i]) - 1;
        }
    }
    index = 0;

    for (int i = 0; i < sensorCount; i++) {
        if (i < sensorCount - 1) {
            index += snprintf(&T01[index], 3, "%d,", typeArray[i]) - 1;
        }
        else {
            index += snprintf(&T01[index], 3, "%d", typeArray[i]) - 1;
        }
    }
    index = 0;

    for (int i = 0; i < sensorCount; i++) {
        if (i < sensorCount - 1) {
            index += snprintf(&T02[index], 5, "%d,", tempArray[i]) - 1;
        }
        else {
            index += snprintf(&T02[index], 5, "%d", tempArray[i]) - 1;
        }
    }
    index = 0;

    for (int i = 0; i < sensorCount; i++) {
        if (i < sensorCount - 1) {
            index += snprintf(&T03[index], 5, "%d,", humArray[i]) - 1;
        }
        else {
            index += snprintf(&T03[index], 5, "%d", humArray[i]) - 1;
        }
    }
    index = 0;

    for (int i = 0; i < sensorCount; i++) {
        if (i < sensorCount - 1) {
            index += snprintf(&T04[index], 5, "%d,", moiArray[i]) - 1;
        }
        else {
            index += snprintf(&T04[index], 5, "%d", moiArray[i]) - 1;
        }
    }
    index = 0;

    for (int i = 0; i < sensorCount; i++) {
        if (i < sensorCount - 1) {
            index += snprintf(&T05[index], 10, "%d,", (resiArrayHI[i] << 16) | resiArrayLO[i]) - 1;
        }
        else {
            index += snprintf(&T05[index], 10, "%d", (resiArrayHI[i] << 16) | resiArrayLO[i]) - 1;
        }
    }
    index = 0;

    for (int i = 0; i < sensorCount; i++) {
        if (i < sensorCount - 1) {
            index += snprintf(&T06[index], 5, "%d,", temp2Array[i]) - 1;
        }
        else {
            index += snprintf(&T06[index], 5, "%d", temp2Array[i]) - 1;
        }
    }
    index = 0;

    for (int i = 0; i < sensorCount; i++) {
        if (i < sensorCount - 1) {
            index += snprintf(&T07[index], 5, "%d,", hum2Array[i]) - 1;
        }
        else {
            index += snprintf(&T07[index], 5, "%d", hum2Array[i]) - 1;
        }
    }
    index = 0;
}

Co máte na mysli hlubokou rekurzí?

Když program běží bez volání funkcí dns_resolv a http_get, na admin webu FULL-C vidím tyto hodnoty využití:

FULL-C status: RUNNING

FC-PROG MEMORY: 64kB
HEAP STATS: curalloc=61016, totfree=1436 maxfree=1376, nget=491 nrel=40
HEAP STATS: bc_locked=26704, stackTop=1492 (of 3072)
SYS: free=360

Jak se v těchto číslech vyznat?

Předem díky,
Jakub

4

Re: Problém s voláním funkcí dns_resolv, http_get

Teprve si to vše přečtu, ale mezitím se můžete podívat sem:

http://wiki.merenienergie.cz/index.php/FULL-C_details
(vysvětlení proč to nemusí fungovat - málo paměti a pročpak to)

a sem:

http://wiki.merenienergie.cz/index.php/FULL-C_tips_and_tricks
(vysvětlení hodnot)

Najdete tam vysvětlení na řadu vašich otázek.

Jak to ale vypadá, váš program je už zkrátka asi moc velký. Zkuste jej upravit - nejde ani tak o zmenšení kódu, jako jeho předělání (aby tam nemuselo být tolik statických polí atd.).

Dále - stáhněte si nový FULLC.exe, ukazuje mnohem detailněji (po překladu) co se s pamětí v SDS děje a jaké jsou jednotlivé velikosti jednotlivých částí programu.

---

píšete:

HEAP STATS: curalloc=61016, totfree=1436 maxfree=1376

Váš program využívá téměř celou pamět a zbývá jen 1436 bajtů (a z toho jde alokovat jeden souvislý blok o nejvíce 1376 bajtech). Toto už nestačí pro provedení zmíněných funkcí.

Pokud nemůžete spotřebu paměti vašeho programu zmenšit (např. jeho přepsáním), musíte přejít na jiné SDS - na variantu 128KB.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !