![]() |
|
Модераторы: bsa |
![]()
|
|
| grisWall |
|
||||||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 28.4.2013 Репутация: нет Всего: нет |
Всем доброго времени суток у меня назрел вопрос. Я решил тут на днях написать программку на Си которая принимает в консоли параметры и создает папку с именем и помещает в неё main.c. Что то типа начальный шаблон для автоматизации создания программ в отдельных папках, а то я тут глянул один раз и ужаснулся что у меня в одной папке столько программ и столько хлама что в пору уже вешаться чем со всем этим разобраться. Я решил написать программку и вроде написал я ее и она мне все создавала. Но вот не задача решил, я начитавшись K&R переписать её указателями. И тут я попал на такую вещь как ошибка сигментирования я то ее реализовал массивами и горя не знал а вот как только я начал делать
и дальше хуже кто-нибудь объясните мне, почему вот такой код вызывает ошибку сигментирования?
при том что все это компилируется молча. Это сообщение отредактировал(а) grisWall - 6.9.2013, 12:05 |
||||||
|
|||||||
| leshiysoft |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 19 Регистрация: 3.8.2007 Репутация: нет Всего: нет |
Если просто, то так:
Потому что в Ваше переменной file лежит указатель на константную строку в сегменте данных, так как вы её задаете прямо в коде. Други словами в куче место под эту переменную не выделялось и аллоков и маллоков небыло. Вот она и ругается, мол, в сегмент данных, содержимое которого формируется в процессе компиляции, нехорошо писать. Нужно руками выделять необходимый объем памяти. |
|||
|
||||
| grisWall |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 28.4.2013 Репутация: нет Всего: нет |
||||
|
||||
| leshiysoft |
|
||||||||
|
Новичок Профиль Группа: Участник Сообщений: 19 Регистрация: 3.8.2007 Репутация: нет Всего: нет |
Правильно так:
Все дело в том, что любая строка в кавычках используемая в коде - это const char*, причем располагается она в секторе данных для чтения. Следовательно, записывать в неё нельзя. Для записи нужно вручную выделить память, например, так:
и незабыть очистить память:
Кстати можно было не вводить новую переменную fileName и использовать строку в кавычках прямо в аргументах функции strcpy:
так как она (строка в кавычках) имеет нужный для strcpy тип : const char* |
||||||||
|
|||||||||
| feodorv |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Переменная file указывает на область в памяти процесса, в которой находятся символы '\t', ' ' ... ' ', '*', '\0' Проблема в том, что эта область памяти защищена от записи. Так её создал и определил компилятор, что вполне корректно, ибо строковый литерал по своей сути - константа. Более того, если Вы создадите ещё одну подобную переменную, указывающую на ту же самую строку:
Что делать? Самый простой способ - это воспользоваться инициализированным массивом:
Добавлено через 2 минуты и 17 секунд А без выделения памяти никак??? Добавлено через 5 минут и 30 секунд Да, нужно заметить, что эта изменяемая память ограничена в размерах - 100 байт и не более. В случае выхода за её пределы:
-------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||
|
|||||||
| leshiysoft |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 19 Регистрация: 3.8.2007 Репутация: нет Всего: нет |
Массив действительно подойдет, так как массив в С - это ничто иное как указатель. И память выделенную под массив не нужно очищать. Но в случае если размера массива вам будет нехватать надо будет переписывать и перекомпилировать программу. Особенно это неприятно и неправильно, когда необходимый размер под строку заранее неизвестен, например, зависит от размера строки введенной пользователем.
|
|||
|
||||
| feodorv |
|
||||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Это да. Довольно часто возникают задачи, в которых необходимый объём памяти заранее не известен. С другой стороны, на мой взгляд, ещё чаще программисты недооценивают возможность воспользоваться массивом))) Но в любом случае придётся тщательно рассчитывать необходимый размер. Чаще всего, этот размер вполне комфортный и ограничен сверху разумной константой, так почему бы в таком случае не использовать массив? Тщательность определения необходимого размера памяти демонстрирует и этот пример:
Хорошо, что здесь sizeof("main.c")+3 меньше или равен чем sizeof("\t* *"). А если больше:
Опять непонятный SIGSEGV? -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||||
|
|||||||
| grisWall |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 18 Регистрация: 28.4.2013 Репутация: нет Всего: нет |
да я кстати замечу что у меня то в коде изначально я реализовал массивами все это дело вот так:
это я уже для эксперименту решил по пробовать получиться может изящнее или эффективнее вот и напробовался блин так что мама не горюй щас все вернул назад даже что-то доработал в старой версии. Так что всем спасибо за дельные советы все очень помогли особенно с malloc и free а по поводу определения размера у массива я тоже взял на заметку... спасибо.
Это сообщение отредактировал(а) grisWall - 6.9.2013, 23:31 |
||||
|
|||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Смотри, есть системные требования, например, для максимальной длины названия файла (вместе с путём). Вердикт. Массиву сразу присваешь такую размерность. Не экономь сотню байтов, зато потом ты лишний раз нигде не будешь удивлятьс. Это раз. -------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| feodorv |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 12 Всего: 45 |
Ну, тут немного другие требования. Готовится вывод на экран в "красивом" виде))) Следовательно, нужно не увеличивать буфер под возможности файловой системы, а ограничить длину имени файла:
Кстати:
48 байт явно мало для строки "\t* *" -------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
||||
|
|||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
Вместо перемещения файлов средствами интерфейса системы конечно же надо дописать специальную прогу к имеющейся помойке, потом ещё одну для её запуска и передаче ей параметров, потом для её запуска и передаче параметров ей и так пока весь винт на это не изведёшь. Так держать. -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
| akizelokro |
|
|||
![]() Крокодил ![]() ![]() Профиль Группа: Участник Сообщений: 761 Регистрация: 30.7.2007 Репутация: 1 Всего: 5 |
Руку на чем-то набивать ему надо
-------------------- a = a + b; b = a - b; a = a - b; |
|||
|
||||
| ТарасАтавин |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 370 Регистрация: 26.8.2013 Репутация: нет Всего: нет |
А про терминальный ноль знаешь? -------------------- Не так всё плохо, как оно есть на самом деле. |
|||
|
||||
![]()
|
| Правила форума "C/C++: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |