Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
perry
Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 20. srpen 2013, 16:30:53 Předmět: Segmentation fault v Linuxu |
|
|
Už jsem dlouho nic nepsal technického, tak je zase čas
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 |
|
|
Deluxe
Založen: 31. 07. 2007 Příspěvky: 235 Bydliště: Oslavany
|
Zaslal: 20. srpen 2013, 16:52:55 Předmět: |
|
|
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. |
|
Návrat nahoru |
|
|
perry
Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 20. srpen 2013, 16:59:32 Předmět: |
|
|
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 |
|
|
TeaTime
Založen: 17. 06. 2011 Příspěvky: 264
|
Zaslal: 20. srpen 2013, 17:02:21 Předmět: |
|
|
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 |
|
|
if.then
Založen: 13. 04. 2008 Příspěvky: 579
|
Zaslal: 20. srpen 2013, 17:06:33 Předmět: |
|
|
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 |
|
|
TeaTime
Založen: 17. 06. 2011 Příspěvky: 264
|
Zaslal: 20. srpen 2013, 17:07:52 Předmět: |
|
|
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 |
|
|
perry
Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 20. srpen 2013, 17:10:07 Předmět: |
|
|
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:
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 |
|
|
TeaTime
Založen: 17. 06. 2011 Příspěvky: 264
|
Zaslal: 20. srpen 2013, 17:11:03 Předmět: |
|
|
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 |
|
|
TeaTime
Založen: 17. 06. 2011 Příspěvky: 264
|
Zaslal: 20. srpen 2013, 17:15:37 Předmět: |
|
|
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 |
|
|
VODA
Založen: 29. 07. 2007 Příspěvky: 1721 Bydliště: Plzeň
|
Zaslal: 20. srpen 2013, 17:16:24 Předmět: |
|
|
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 |
|
|
TeaTime
Založen: 17. 06. 2011 Příspěvky: 264
|
Zaslal: 20. srpen 2013, 17:24:47 Předmět: |
|
|
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 |
|
|
perry
Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 20. srpen 2013, 17:30:24 Předmět: |
|
|
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ř.
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
==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
|
_________________ Perry.cz |
|
Návrat nahoru |
|
|
VODA
Založen: 29. 07. 2007 Příspěvky: 1721 Bydliště: Plzeň
|
Zaslal: 20. srpen 2013, 17:43:11 Předmět: |
|
|
perry napsal: |
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 |
|
|
perry
Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 20. srpen 2013, 17:49:26 Předmět: |
|
|
VODA
Jo.. pravda, vychází to z Visualka. _________________ Perry.cz |
|
Návrat nahoru |
|
|
perry
Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 20. srpen 2013, 17:58:51 Předmět: |
|
|
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 ... 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 _________________ Perry.cz
Naposledy upravil perry dne 20. srpen 2013, 18:07:28, celkově upraveno 2 krát |
|
Návrat nahoru |
|
|
|