LINUX.ORG.RU

Ошибка сегментирования в Cи «Баг или я дурак_2»

 


0

1
void sque( char str_one[], char str_too[])
{  
    int count_one=0;
    int count_too=0;
    
  while(str_too[count_too]!='\0')
  {   printf("%d\n",count_one);//так яснее
      
      if(str_one[count_one]=='\0')
      {
         count_one=0;
         count_too++;
      };

      if(str_one[count_one]==str_too[count_too])
      { 
        str_one[count_one]='_'; //вызывает ошибку сегментирования, схерали? gcc от 4.2 до 4.7
        
      };
        count_one++;    
   };

  printf("%s\n",str_one);

};

int main()
{   

sque("11g111f111511","55gfnf5gfhnrtfjn5sgdg5");


  return 0;
};
★★★★★

Последнее исправление: cetjs2 (всего исправлений: 1)

str_one[count_one]='_'; //вызывает ошибку сегментирования, схерали? gcc от 4.2 до 4.7

Потому что str_one это не массив.

olibjerd ★★★★★
()

Почему ты думаешь, что литералы можно менять?

AptGet ★★★
()

ок, спасибо, туплю.

Dron ★★★★★
() автор топика
Ответ на: комментарий от vapor

Ну и печатает 11_111_111_11 как и надо.

2 пишется как two, а не как too

vapor
()
Ответ на: комментарий от olibjerd

да, но литерал это массив.

Dron ★★★★★
() автор топика

Всё потому, что «11g111f111511» константа

vapor
()
Ответ на: комментарий от olibjerd

функция должна принимать не char, а указатели, то есть char *

Это не поможет, все равно будет ошибка сегментирования. Потому что, как отметили ниже, это литералы.

А вот так будет работать:

    char* s1 = strdup("11g111f111511");
    char* s2 = strdup("55gfnf5gfhnrtfjn5sgdg5");
    sque(s1, s2);

zhuravlik ★★★★
()
objdump -j .rodata -d test.elf 

test.elf:     file format elf64-x86-64


Disassembly of section .rodata:

00000000004006c8 <_IO_stdin_used>:
  4006c8:       01 00 02 00 25 64 0a 00 35 35 67 66 6e 66 35 67     ....%d..55gfnf5g
  4006d8:       66 68 6e 72 74 66 6a 6e 35 73 67 64 67 35 00 31     fhnrtfjn5sgdg5.1
  4006e8:       31 67 31 31 31 66 31 31 31 35 31 31 00              1g111f111511.
exception13 ★★★★★
()

Всем спасибо, буду внимателен при передаче аргументов функции. Не оправдываюсь, но всё же вызов функции писал раньше самой функции, а потом внимания на сам вызов не обращал в том и беда моя была :)

Dron ★★★★★
() автор топика
Ответ на: комментарий от Dron

Во, вам exception13 показал, что при таком определении.

char *a=«5gffgfg»;

данные находятся в .rodata (т.е. read only data)

vapor
()
Ответ на: комментарий от olibjerd

массивы и передаются в функцию по указателю, так что

void foo(char *arr);
void foo(char arr[]);
void foo(char arr[42]);
все один хрен. проблема, как уже сказали в том, что автор пытался изменять константные литералы.

vvviperrr ★★★★★
()
Ответ на: комментарий от vvviperrr

проблема, как уже сказали в том, что автор пытался изменять константные литералы.

дело не в константе а в том что она размещена в секции с RO

exception13 ★★★★★
()
Ответ на: комментарий от vapor

Скорее всего, просто нужно иметь определенный опыт, как и везде, чтобы на них не попадаться. :)

Увы или к счастью, у меня опыт с java/c# куда больше, чем с С. И к счастью или увы, что нет вообще никакого опыта с С++. :)

zhuravlik ★★★★
()
Ответ на: комментарий от exception13

это просто следствие. даже если строковой литерал лежит не в .rodata section (вот билдер например не кладет их в ro, насколько я помню) это не значит, что можно их изменять.

vvviperrr ★★★★★
()

Почитай K&R хотя бы, чтобы таких нелепых ошибок не было, а потом Pointers on C

anonymous
()
Ответ на: комментарий от vvviperrr

это просто следствие. даже если строковой литерал лежит не в .rodata section (вот билдер например не кладет их в ro, насколько я помню) это не значит, что можно их изменять.

на уровне синтаксиса они не определены как константы так что явного запрета нет.

exception13 ★★★★★
()
Ответ на: комментарий от exception13

в стандарте сказано, что изменение строкового литерала приводит к ub. то, что это привело к попытке изменения данных в ro секции - дело десятое.

vvviperrr ★★★★★
()
Ответ на: комментарий от exception13

на уровне синтаксиса они не определены как константы так что явного запрета нет.

И как же тогда они определены?

madcore ★★★★★
()
Ответ на: комментарий от exception13

на уровне синтаксиса они не определены как константы так что явного запрета нет.

На сколько я помню, char[] эквивалентно char * const. Что является неконстантным указателем на константные данные.

@Dron: будь внимаетелен с C-шними «char * const», «const char *» и «const char * const».

anonymous
()
Ответ на: комментарий от anonymous

На сколько я помню, char[] эквивалентно char * const. Что является неконстантным указателем на константные данные.

Что является неконстантным указателем на константные данные

анон такой анон. в твоем примере КОНСТАНТНЫЙ указатель на НЕКОНСТАНТНЫЕ данные

vvviperrr ★★★★★
()
Ответ на: комментарий от vvviperrr

анон такой анон. в твоем примере КОНСТАНТНЫЙ указатель на НЕКОНСТАНТНЫЕ данные

Пишу по памяти. А так - да, ты прав. Я всё перепутал.

anonymous
()
Ответ на: комментарий от exception13

на уровне синтаксиса они не определены как константы так что явного запрета нет.

Простите что? Кто не определен? Данные константные. Параметры нет. Но передаются константные данные. Кстати вроде в Си++ такое и не скомпилится. Нэ?

Dudraug ★★★★★
()
Ответ на: комментарий от anonymous

Что является неконстантным указателем на константные данные.

Наоборот.

Dudraug ★★★★★
()
Ответ на: комментарий от Dudraug

Простите что? Кто не определен? Данные константные.

okay. а теперь представь что это фирмварь т.е. из elf с секциями и атрибутами секций мы делаем objcopy в binary. допустим что эти строки у нас будут использоваться под некий буфер и все будет прекрасно работать (естественно при соблюдении array boundary)

exception13 ★★★★★
()
Ответ на: комментарий от exception13

и все будет прекрасно работать

Это называется UB. Стандарт запрещает изменять константные данные. Не думаю, что передавать строковый летерал в функцию и потом его менять - это хорошая идея.

Dudraug ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.