.[ ČeskéHry.cz ].
Segmentation fault v Linuxu
Jdi na stránku 1, 2, 3  Další
 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> C / C++
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
perry



Založen: 28. 07. 2009
Příspěvky: 866

PříspěvekZaslal: 20. srpen 2013, 16:30:53    Předmět: Segmentation fault v Linuxu Odpovědět s citátem

Už jsem dlouho nic nepsal technického, tak je zase čas Very Happy

Mám problém s C++ programem. Napsal jsem ho na woknech (ve VS), odladil na memory leaky a na woknech všechno šlape jak má. Bohužel mám problém pod Linuxem. Občas (náhodně, cca. každé 20x spuštění) se mi program složí s chybou "Segmenation fault". Když ho hned potom pustím znovu (stejný vstup), tak vše doběhne OK.

Problém je, že absolutně nevím, jak tu chybu najít, když se mi jí nedaří ani nasimulovat. Navíc k Linuxu mám přístup pouze přes terminál, a nějak nejsem "konzole only", takže mistrovství je pro mě spustit build z makefilu.

Přidal jsem si kontrolní printf do programu, jenomže pokaždé to vypíše od startu k "jinému bodu", nejčastěji to ale nevypíše nic a končí to někde v tomhle:

kód:
std::vector<MyStringAnsi> inputFiles;
MyStringAnsi mapFile = "";
MyStringAnsi output = "";
MyStringAnsi coordinatesDataFileName = "";
MyStringAnsi outputCache = "";
MyStringAnsi type = "data";

for (int i = 1; i < argc; i++)
{
    if ((argv[i][0] == '-') && (argv[i][1] == 'm'))
    {
        mapFile = argv[i + 1];
    }

    if ((argv[i][0] == '-') && (argv[i][1] == 'd'))
    {
        inputFiles.push_back(argv[i + 1]);
    }

    if ((argv[i][0] == '-') && (argv[i][1] == 'o'))
    {
        output = argv[i + 1];
    }

    if ((argv[i][0] == '-') && (argv[i][1] == 'f'))
    {
        coordinatesDataFileName = argv[i + 1];
    }

    if ((argv[i][0] == '-') && (argv[i][1] == 'c'))
    {
        outputCache = argv[i + 1];
    }

    if ((argv[i][0] == '-') && (argv[i][1] == 't'))
    {
        type = argv[i + 1];
    }
}


Ten MyStringAnsi by měl být OK. Používám ho i jinde a nikde stejný problém není. Argumenty mi taky nepřetékají imho, protože jsou pořád stejné při každém běhu (i pořadí). Hned za tímhle je printf, který se už většinou nevypíše.
_________________
Perry.cz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Deluxe



Založen: 31. 07. 2007
Příspěvky: 235
Bydliště: Oslavany

PříspěvekZaslal: 20. srpen 2013, 16:52:55    Předmět: Odpovědět s citátem

Na linuxu by mohl pomoct http://valgrind.org/, pokud je k dispozici. Problemy muze delat, pokud se pouziva hodne externich knihoven, ale jinak mi par vlasu uz zachranil. Wink
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
perry



Založen: 28. 07. 2009
Příspěvky: 866

PříspěvekZaslal: 20. srpen 2013, 16:59:32    Předmět: Odpovědět s citátem

Valgrind znám, externí knihovny žádné nemám. Nicméně nějak se mi nezdá pravděpodobné, že by na woknech byl program bez leaků a na Linuxu se tam objevily...
_________________
Perry.cz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
TeaTime



Založen: 17. 06. 2011
Příspěvky: 263

PříspěvekZaslal: 20. srpen 2013, 17:02:21    Předmět: Odpovědět s citátem

No buď můžeš použít program valgrind (spusť příkazem 'valgrind <filename>', kde <filename> je název spustitelného souboru), nebo gdb (spusť příkazem 'gdb <filename>', pak zadej 'run' a až to padne, tak dej 'backtrace').

Valgrind ti vypíše podezřelé a chybné přístupy do paměti a gdb ti vypíše backtrace kde to spadlo.

Oba programy toho vypíšou více, když tvůj program zkompiluješ v gcc s příznakem '-g'. Možná že se ti to s tím už kompiluje, jinak by bylo potřeba někam v nastavení buildu přidat do proměnné CFLAGS nebo tak nějak příznak '-g'.

Jinak rozdíl mezi linuxem a windows je myslím v tom, že windows nulují proměnné při inicializaci kdežto linux někdy ne.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
if.then



Založen: 13. 04. 2008
Příspěvky: 579

PříspěvekZaslal: 20. srpen 2013, 17:06:33    Předmět: Odpovědět s citátem

Mých pět korun: proměnná i nabývá hodnot od 1 do argc-1 a poté tam máš
kód:
mapFile = argv[i + 1];

Což prostě nemůže skončit dobře - bereš z argv[argc], což je jasný array overflow. Kromě toho inputy pod dva znaky. Řešením by bylo něco jako
kód:

for (int i = 1; i < (argc - 1); i++) {
  if (argv[i][0] == '\0' || argv[i][1] == '\0')
    continue;
  ...


Ale pokud máš sensible parametry, tak tohle asi stejně nepomůže.
_________________
For guns and glory, go to www.ceske-hry.cz.
For work and worry, execute VC++.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
TeaTime



Založen: 17. 06. 2011
Příspěvky: 263

PříspěvekZaslal: 20. srpen 2013, 17:07:52    Předmět: Odpovědět s citátem

Teď mě napadá - co když bude ten cyklus v poslední iteraci? V 'i' bude 'argc-1' ale číst budeš následující řádek 'i+1' což je rovno hodnotě 'argc', což je mimo rozsah pole argv.

Na tom by to možná mohlo padnout v závislosti na rozložení zásobníku (což by třeba mohlo způsobit tu odlišnost na linux/win). Zas tak se v tom nevyznám, jestli to na tom může padat nebo jestli to na tom může nepadat, ale ze svého laického pohledu bych z toho měl obavy.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
perry



Založen: 28. 07. 2009
Příspěvky: 866

PříspěvekZaslal: 20. srpen 2013, 17:10:07    Předmět: Odpovědět s citátem

TeaTime

Funguje valgrind i pro release build ? Nebo to muisím vybuildovat "jako debug" bez optimalizací.

if.then

O tom vím, ale to nikdy nepřeteče, protože parametry mají formát:

kód:
-<typ> <hodnota>

a uvnitř toho ifu je vždycky ten následující řetězec (tzn. <hodnota> => i + 1). Hodnota má vždycky délku > 5
_________________
Perry.cz


Naposledy upravil perry dne 20. srpen 2013, 17:11:44, celkově upraveno 1 krát
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
TeaTime



Založen: 17. 06. 2011
Příspěvky: 263

PříspěvekZaslal: 20. srpen 2013, 17:11:03    Předmět: Odpovědět s citátem

if.then napsal:
Kromě toho inputy pod dva znaky.


S tím problém být nemůže. Pokud ten řetězec má nula znaků, tak na nulté pozici bude nula, takže podmínka `argv[i][0] == '-'` se vyhodnotí jako false a druhá polovina podmínky se nebude vyhodnocovat. Když to bude mít jeden znak, tak to bude obdobné, akorát to zamítne podmínku až v druhé části podmínky.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
TeaTime



Založen: 17. 06. 2011
Příspěvky: 263

PříspěvekZaslal: 20. srpen 2013, 17:15:37    Předmět: Odpovědět s citátem

perry napsal:
TeaTime

Funguje valgrind i pro release build ? Nebo to muisím vybuildovat "jako debug" bez optimalizací.


Jo, funguje, jen to při nepřítomnosti debug symbolů nevypisuje čísla řádků, názvy identifikátorů a výtažky z kódu, což je nepříjemné. A díky optimalizacím to nemusí vypsat hodnoty některých vyoptimalizovaných parametrů, ale to člověka většinou nezajímá.

Ale i optimalizované release buildy kolikrát obsahují debug symboly.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
VODA



Založen: 29. 07. 2007
Příspěvky: 1692
Bydliště: Plzeň

PříspěvekZaslal: 20. srpen 2013, 17:16:24    Předmět: Odpovědět s citátem

TeaTime napsal:
Jinak rozdíl mezi linuxem a windows je myslím v tom, že windows nulují proměnné při inicializaci kdežto linux někdy ne.

Od které doby? Já kompiluji jak přes gcc na linuxu tak přes MinGW na windows a nikdy se mi nestalo, že by se proměná při inicializaci vynulovala...
Nevím, jak si to dělá teda visuálko...

Perry:
Zkoušíš to na nativních linuxech? Protože když jsem kdysi dělal semestrálku na ZOS, tak má implementace programu s vlákny (pthread) na linuxech ve virtualboxu občas končila právě se segfault. Myslel jsem, že je chyba u mě, ale nakonec jsem to zkusil na X nativních distribucích a ani jednou se mi to nestalo, takže jsem příčinu svedl na virtualbox.

Mimochodem, já když nemohu najít chybu a jsem línej použít nějaký nástroj, tak si dávám printf (+fflush) všude možně, většinou hledám chybu po vzoru binárního vyhledávání. Ještě se mi nestalo, že bych chybu neodhalil...
_________________
Opravdovost se pojí s trýzní...
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
TeaTime



Založen: 17. 06. 2011
Příspěvky: 263

PříspěvekZaslal: 20. srpen 2013, 17:24:47    Předmět: Odpovědět s citátem

VODA napsal:
TeaTime napsal:
Jinak rozdíl mezi linuxem a windows je myslím v tom, že windows nulují proměnné při inicializaci kdežto linux někdy ne.

Od které doby? Já kompiluji jak přes gcc na linuxu tak přes MinGW na windows a nikdy se mi nestalo, že by se proměná při inicializaci vynulovala...
Nevím, jak si to dělá teda visuálko...


No tady jsem vskutku na tenkém ledě, nechce se mi to teď zkoušet. Ono ve specifikaci je samozřejmě, že se nic nenuluje. Ale kdysi dávno jsem to nějak testoval a teď mám pocit, že to bylo takhle (na windows byly nuly vždy a na linuxu většinou), ale ruku do ohně za to nedám. Možná nešlo o nulování, ale prostě o alokaci paměti obsahující samé nuly, ale to je z našeho hlediska to samé.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
perry



Založen: 28. 07. 2009
Příspěvky: 866

PříspěvekZaslal: 20. srpen 2013, 17:30:24    Předmět: Odpovědět s citátem

citace:

Jinak rozdíl mezi linuxem a windows je myslím v tom, že windows nulují proměnné při inicializaci kdežto linux někdy ne.


To je myslím pravda. např.
kód:
int * i;

Na woknech tam bude NULL, na linuxu tam může zůstat myslím bordel.

Každopádně pouštím to v nativním prostředí (distribuce CentOS). Ty debug výpisy tam právě mám, ale pokaždé to vypíše jiný počet. Někdy to spadne hned, jindy to něco vypíše.

EDIT
Projel jsem to Valgrindem a

citace:

==12104==
==12104== HEAP SUMMARY:
==12104== in use at exit: 0 bytes in 0 blocks
==12104== total heap usage: 29,489 allocs, 29,489 frees, 65,200,519 bytes allocated
==12104==
==12104== All heap blocks were freed -- no leaks are possible
==12104==
==12104== ERROR SUMMARY: 4 errors from 1 contexts (suppressed: 15 from Cool
==12104==
==12104== 4 errors in context 1 of 1:
==12104== Invalid read of size 1
==12104== at 0x4006A93: strlen (mc_replace_strmem.c:275)
==12104== by 0x804A44D: MyStringAnsi::CreateNew(char const*) (in ...)
==12104== by 0x8074ECE: AbstractMapa::AddData(MyStringAnsi const&) (in ...)
==12104== by 0x8078D45: main (in ...)
==12104== Address 0x462eca3 is 0 bytes after a block of size 2,387 alloc'd
==12104== at 0x4005FAD: operator new[](unsigned int) (vg_replace_malloc.c:258)
==12104== by 0x8074E9D: AbstractMapa::AddData(MyStringAnsi const&) (in ...)
==12104== by 0x8078D45: main (in ....)
==12104==
--12104--
--12104-- used_suppression: 15 dl-hack3
==12104==
==12104== ERROR SUMMARY: 4 errors from 1 contexts (suppressed: 15 from Cool

_________________
Perry.cz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
VODA



Založen: 29. 07. 2007
Příspěvky: 1692
Bydliště: Plzeň

PříspěvekZaslal: 20. srpen 2013, 17:43:11    Předmět: Odpovědět s citátem

perry napsal:
kód:
int * i;

Na woknech tam bude NULL, na linuxu tam může zůstat myslím bordel.

Říkám, že je to blbost, možná že visuálko proměnné nuluje, ale není to nic windows specific. Závisí to na překladači. Obvykle se to nenuluje, což vychází z assembleru.
_________________
Opravdovost se pojí s trýzní...
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
perry



Založen: 28. 07. 2009
Příspěvky: 866

PříspěvekZaslal: 20. srpen 2013, 17:49:26    Předmět: Odpovědět s citátem

VODA

Jo.. pravda, vychází to z Visualka.
_________________
Perry.cz
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
perry



Založen: 28. 07. 2009
Příspěvky: 866

PříspěvekZaslal: 20. srpen 2013, 17:58:51    Předmět: Odpovědět s citátem

Tak jsem opravil tu chybu (četl jsem freadem v binárním módu data a pak na ně udělal strlen, což je pěkná kravina Embarassed ... zapomněl jsem nakonec dohodit '\0'), co psal valgrind... Nechápu, proč to ale neudělalo memory leak a nepadalo to na woknech.

Teď se uvidí, jestli to zase spadne. Zatím díky za rady... případně se ještě ozvu Smile
_________________
Perry.cz


Naposledy upravil perry dne 20. srpen 2013, 18:07:28, celkově upraveno 2 krát
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> C / C++ Časy uváděny v GMT + 1 hodina
Jdi na stránku 1, 2, 3  Další
Strana 1 z 3

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna