Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: asd 18. 01. 2013, 16:08:13

Název: C a SIGSEGV při dereferencování
Přispěvatel: asd 18. 01. 2013, 16:08:13
Caute. Mam takyto kod:

Kód: [Vybrat]
    1 #include <stdio.h>
    2 #include <ctype.h>
    3
    4 void strtoupper(char *str)
    5 {   
    6     while (*str) // na znaku \0 sa cyklus zastavi
    7     {   
    8         *str = toupper(*str); // dereferencuje aktualny znak na ktory ukazuje str, zavola toupper a nahradi tento znak
    9         str++; // posunie ukazatel o 1
   10     }
   11 }
   12
   13 int main()
   14 {   
   15     char *str = "hello world";
   16     strtoupper(str);
   17 
   18     printf("%s\n", str);
   19 
   20     return 0;
   21 }

a pada mi to hned pri prvom prechode cyklom:
Kód: [Vybrat]
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400571 in strtoupper (str=0x40066c "hello world") at case.c:8
8 *str = toupper(*str);
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: pipipi 18. 01. 2013, 16:28:09
protoze
char *str = "hello world";
je read only

char str[] = "hello world";
bude ok
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: pipipi 18. 01. 2013, 16:37:28
napriklad tady je k tomu nejaka diskuse

http://stackoverflow.com/questions/1704893/how-is-read-only-memory-implemented-in-c
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: Mirek Prýmek 18. 01. 2013, 16:41:28
char str[] = "hello world";
bude ok
Nebude. Je to uplne stejna chyba.
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: pipipi 18. 01. 2013, 16:47:04
tomu nerozumim, proc?

char str[] = "hello world";
je snad uplne totez co
char str[12] = "hello world";

no a tohle uz mi snad prekladac nekde doprcic neda
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: DarkKnight 18. 01. 2013, 16:54:01
char str[] = "hello world";
bude ok
Nebude. Je to uplne stejna chyba.

Ale bude, je rozdil mezi char * x  a char x[]
pokud to chce resit pres char * x, musi nejdrive naalokovat pamet a pak to tam nakopirovat
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: Mirek Prýmek 18. 01. 2013, 17:04:02
Ale bude, je rozdil mezi char * x  a char x[]
No mas pravdu, funguje to stejne jako = {'a','b',0}. To je az desivy, jak clovek rychle zapomina :(
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: pipipi 18. 01. 2013, 17:05:55
mimochodem

int main() {   
     char str[] = "hello world";
     puts(str); 
     return 0;
 }


prelozi gcc jako
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    leal    20(%esp), %eax
    movl    %eax, (%esp)
    movl    $1819043176, 20(%esp)
    movl    $1870078063, 24(%esp)
    movl    $6581362, 28(%esp)
    call    puts
    xorl    %eax, %eax
    leave
    ret


takze tam skutecne vytvari na zasobniku lokalni promennou, a pak do ni cpe ten string
1819043176 = 0x6c6c6568 = "lleh"
1870078063 = 0x6f77206f = "ow o"
6581362 = 0x646c72 = "\0dlr"

takze toto proste musi fungovat, pokud to teda neni tak nejak platformove zavisle
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: Mirek Prýmek 18. 01. 2013, 17:16:59
prelozi gcc jako
Z toho, jak co gcc prelozi, bych asi radsi zadne zavery nevyvozoval :)

Ale kazdopadne jsi mel pravdu, standard to rika jasne: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf str. 144, example 8

Za zapomenuti takhle zakladni veci se asi dneska budu cervenat az do pulnoci :))
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: asd 18. 01. 2013, 17:19:25
Dakujem vsetkym za odpovede/prispevky  :)
Název: Re:C a SIGSEGV při dereferencování
Přispěvatel: pipipi 18. 01. 2013, 17:28:41
no ja to gcc uvedl spis jako zajimavost, jak to pak vypada, kdyz uz jsem to zkousel
tak jsme si aspon trochu zopakovali C ;)