C++ - Heap corruption detected
Ahoj! Tak jsem zase tady - posunul jsem se k práci s dynamickým polem a zkusil jsem to zkombinovat se sčítáním binárních čísel (btw je to i úkol do školy, ale základní verzi se statickými poli už jsem odevzdal :D ) - načtu řetězec, obě čísla načtu do polí, převedu pole na stejnou velikost, neinicializované buňky vyplním nulami a sčítám - program čísla sečte, jen mi vždy vyhodí hlášku "Heap corruption detected". Ať dělám, co dělám, nemůžu přijít na to, kde "hrabu" do paměti - poradíte?
Moc díky za odpovědi, Katsu
#include<iostream>
#include<string>
using namespace std;
int main(){
string vstup;
int a = 0;
int max = 0; //pocet prvku ve vice inicializovanem poli
cout << "Zadejte dve binarni cisla:" << endl;
getline(cin, vstup);
int delka = vstup.length();
//zjisteni delky retezcu
int prep2 = 0;
int delka1 = 0;
int delka2 = 0;
for(int i = delka - 1; i >= 0; --i){
if(vstup[i] == ' '){
++prep2;
continue;
}
if(prep2 == 0){
++delka1;
}else if(prep2 == 1){
++delka2;
}
}
int delka3;
if(delka1 < delka2){
delka3 = delka2;
}else{
delka3 = delka1;
}
int *cislo1 = new int[delka3];
int *cislo2 = new int[delka3];
int j = 0;
int k = 0;
int mezera = 0;
for(int i = delka - 1; i >= 0; --i){
if(vstup[i] == ' '){
++mezera;
++a;
continue;
}
if(vstup[i] == '1' || vstup[i] == '0'){
if(a == 0){
cislo1[j] = vstup[i]-48;
++j;
}else{
cislo2[k] = vstup[i]-48;
++k;
}
}else{
cout << "Nespravny vstup." << endl;
return 0;
}
if(j > max){
max = j;
}else if(k > max){
max = k;
}
}
int *soucet = new int[max+1];
if(mezera != 1){
cout << "Nespravny vstup." << endl;
return 0;
}
//vyplneni zbytku poli 0-mi
for(int i = j; i <= delka3; ++i){
cislo1[i] = 0;
}
for(int i = k; i <= delka3; ++i){
cislo2[i] = 0;
}
int bon = 0; //"bonus" pri scitani, prechazejici na dalsi pozici
int b = 0;
for(int i = 0; i <= max; ++i){
if(cislo1[i] + cislo2[i] + bon == 0){
soucet[b] = 0;
bon = 0;
}else if(cislo1[i] + cislo2[i] + bon == 1){
soucet[b] = 1;
bon = 0;
}else if(cislo1[i] + cislo2[i] + bon == 2){
soucet[b] = 0;
bon = 1;
}else if(cislo1[i] + cislo2[i] + bon == 3){
soucet[b] = 1;
bon = 1;
}
++b;
}
int zkouska = 0;
cout << "Soucet: ";
for(int i = max; i >= 0; --i){
if(soucet[i] == 1){ //kontrola 1 mezery
zkouska = 1;
}
if(zkouska == 1){
cout << soucet[i];
}
if(i == 0 && zkouska == 0){
cout << 0;
}
}
cout << endl;
delete [] cislo1;
delete [] cislo2;
delete [] soucet;
return 0;
}
Nemam cas to cele kontrolovat ale za prve kazde vyvojove prostredie umoznuje debugovat krok za krokom a v pripade takeho problemu by to malo zastat na tom probleme a vies si pozret premenne. Nauc sa pouzivat debugger, inac budes pri komplikovanejsich veciach uplne strateny.
Za druhe proste niekde zapisujes do pola na vyssi index jak je velkost pola. Ked sa take nieco stava tak to znamena ze mas uplne nahovno vymysleny cely koncept resp. mas v nom sam chaos (ze co je v ktorej premennej a preco, napr. mas viac premennych ktore urcuju defakto to iste a je medzi nimi nekonzistencia apod). Skus si premyslet cely koncept ze ako to urobit tak aby sa ti nestavalo ze niekam zapisujes nezmysly.
Jakej koncept? Chudaka jsi ho zkritizoval, pritom "do pole vyssi index jak je velikost pole" neznamena vsechno na prd, naopak typicky to znamena spatnou/neinicializovanou proměnnou či překlep.
S tymto ale nesuhlasim. Prepisanie mimo pola je uplne najhrubsia hrubka to sa proste dobremu koderovi IMHO nesmie stat ani keby neviemco bolo. A aj keby len neinicializoval premennu tak to je potom tiez chaos v koncepte premennych
tym netvrdim ze mne sa to nikdy nestalo (uz sa nepamatam :D) ale ak, tak to bol pre mna alarm signal ze "trubka zamysli sa mas v tom uz chaos" :)
Zkusil jsem napsat kompletně nový kód, problém mi dělá načítání hodnoty do cislo2 (64. řádek) - hodnoty se načtou, ale jakmile program opustí cyklus, ihned se cislo2[0] a cislo2[1] přepíšou na -8...(strašně moc čísel :D) - čím to může být? Za chvíli mi z toho asi uletí hlava :D
for(int j = i+1; j <= b; ++j)
cislo2[j - i+1] = vstup[j]-48;
}
cout << cislo2[0] << cislo2[1] << cislo2[2] << endl;
najprv zober povodny program a proste len oprav na 2 miestach vo for to i <= delka3 na i < delka3
Aj potom to hadze stack corruption? Lebo iny problem som tam nenasiel v tom povodnom kode. Nechce sa mi teraz studovat dalsi kod, boli ma hlava :D Mozno neskor.
Pak to vypíše necelý výsledek (např 10 místo 1010 při zadání 101 + 101 - myslím, že to prostě nezadá to první 1ku, takže program odstraní 0 a vypíše jen 10...). Jak říkám, bez delete[] na konci to fungovalo, ale netuším proč :D
nefungovalo to nikdy ptz tam prepisujes stack. Ked to pise necely vysledek tak mas chybu este niekde inde, nekontroloval som to cele len miesta kde prepisujes nejaky buffer a to s tym i <= delka3 bolo prave jedno take miesto.
Tvoj problem podla mna je
j - i+1
prekladac neni jasnovidec bud j - (i+1) alebo j - i - 1.
Inac robis moc zlozito vsetko. ja by som dynamicky vytvoril len pole pre vysledok a ratal by som to rovno zo vstupu. Tie polia cislo1 a cislo2 vytvaras uplne zbytocne.
Inac len tak mimochodom:
staci takto:
alebo
je presa to iste co
Já jsem taky vůl :D Díky
jinak, i v tomhle vidím chybu, doplňuju nuly, ale až za zadané číslo, tj. ve výsledku pak počítám třeba s 00100 :D
Takže to zkusím ještě jednou, jen mě zajímá - když mám třeba 001 00001, jak s tím mám počítat, když nejsou čísla stejně dlouhá (proto jsem vytvářel ta další pole)?
Napr. ze na zaciatku si nastavis 2 premenne "pozicia_cislo1" a "pozicia_cislo2" na index poslednej cifry cisel vo vstupnom poli, a premenne zaciatok_cislo1 a zaciatok_cislo2 na poziciu prvej cifry vo vstupnom poli.
Potom len vytvoris vystupne pole, a mozes hned ratat, nieco ako
P.S. zaklad optimalneho programovania je okrem inych veci aj zakazdym ked chces urobit novu premennu alebo pole sa najprv zamyslet co uz mam v stavajucich premennych a poliach, a nevytvarat zbytocne nove premenne a polia so stejnymi datami ak uz tie data niekde mam v stavajucej premennej. Akurat ked chcem nejaku premennu menit a zartoven si ale aj zachovat povodnu hodnotu tak novu premennu samozrejme potrebujem. V mojom pripade to su tie pozicia_cisla1 a 2, tie chcem v cykle menit tak preto som ju vytvoril extra, aj ked poziciu poslednej cifry by som si vedel zakazdym vyratat z premennych ktore som uz mal.
Ale nerob si stres, optimalne dnes neprogramuje uz asi skoro nikto ani v profesionalnom celosvetovom meritku, mozog je totiz celosvetovo nedostatkovy tovar :D Dnes ide len o to zaskrtnut v nejakom dementnom managerskom SW ze je naplanovany bod implemented a accepted, a ziaden flag ze "je to uplna sracka" manager v programe nema takze to nikoho nezaujima :D
Vies co zober ten povodny program a toto
zmen na
pretoze ked pises ze ti po tom zmeneni <=delka3 na <delka3 blbne najvyssia cifra tak evidentne pouzivas z tych poli asi aj ten dalsi znak ktory si tam nemal. Funguje to potom?
Super, tebe musím někdy pozvat na pivo :D Moc díky
A vyskytl se ještě jeden (a snad už poslední) problém - školní systém mi to nebere, protože prý mám 2 neuvolněné paměťové bloky - jak je to možné, když na konci používám ke všem 3 polím delete?
neviem co myslis tym skolni system, ale skusal si to uz aj opravene? Pretoze ten povodny program ak prepisal nieco mimo pola tak mohol prepisat udaje o tom poli a potom program nevie co ma vlastne uvolnit. prepisovanie mimo pola je ten najvacsi bubak ktory by ta mal strasit pri kazdom riadku :D preto na to treba mysliet a cykly robit tak aby indexy uplne nabeton nemohli prekrocit velkost pola do ktoreho zapisujem :) Alebo si urobit triedu "dyn_pole" a pristupy umoznit len cez metodu a v nej kontrolovat index.
Ak to pinda aj u opraveneho programu tak daj vediet co presne to hlasi.
Nakonec jsem si všiml, že u ošetření nesprávných vstupů jsem zapomněl mazat alokovanou paměť + jsem udělal významný objev - ty "samoopravovací" systémy neberou knihovny jako třeba vld.h (od Visual Leek Detector). Takže ještě jednou moc díky za rady, už to funguje...