Доброго времени суток.
Нужно описать массив неизвестного количества строк неизвестной длины в Си.Пока имею следующее решение (код примерный, так как он на рабочем компе)
/* Глобальная переменная*/
char *mass[];/* Функция, генерирующая новую строку в массиве*/
int new_mass_str(char* str, int num)
{
mass[num] = (char *)malloc(sizeof(str));
}Работает до 432 malloc'a, на 433 выпадает с сегфаултом.
Что-то мне подсказывает, что фейл в объявлении глобальной переменной, но как ее по другому объявить - ума не приложу. И почему-то всегда именно 433-е выделение памяти (запись 433 строки) сегфолтит.Подробное описание задачи:
Используется inotify для слежением за директориями. Пишу рекурсивное наблюдение с помощью ftw(). Так как inotify не возвращает полный путь до файла, а только имя файла и номер дескриптора слежения[wd], где произошли изменения, то приходится писать массив путей, скоррелированный с дескрипторами наблюдения (что-то вроде path[wd]).
Если есть какие-то еще варианты - буду рад выслушать. Но решение вопроса о массиве тоже хотелось бы узнать.Заранее благодарен.
> Доброго времени с уток.1. Пока не напишешь своей ОС, не юзай указатели на массивы!
2. sizeof(char *str) == SIZE_OF_CHAR
>> Доброго времени с уток.
> 1. Пока не напишешь своей ОС, не юзай указатели на массивы!
> 2. sizeof(char *str) == SIZE_OF_CHARОпс, извиняюсь
не так написал.
...
mass[num] = (char *) malloc (strlen(str));
...
> Опс, извиняюсь, не так написал.Тут много полезного
http://faqs.org.ru/progr/c_cpp/cfaqrus.htm
>[оверквотинг удален]
> 433-е выделение памяти (запись 433 строки) сегфолтит.
> Подробное описание задачи:
> Используется inotify для слежением за директориями. Пишу рекурсивное наблюдение с помощью
> ftw(). Так как inotify не возвращает полный путь до файла, а
> только имя файла и номер дескриптора слежения[wd], где произошли изменения, то
> приходится писать массив путей, скоррелированный с дескрипторами наблюдения (что-то вроде
> path[wd]).
> Если есть какие-то еще варианты - буду рад выслушать. Но решение вопроса
> о массиве тоже хотелось бы узнать.
> Заранее благодарен.Решил проблему:
char** mass;
int mass_size = 0;
...
int new_mass_str(char* str, int num)
{
if (mass == NULL)
{
mass_size = strlen(str);
mass = (char**) malloc(mass_size);
}
else
{
mass_size = mass_size + strlen(str);
mass = (char**)realloc(mass, mass_size);
}
...
mass[num] = (char *)malloc(sizeof(str));
}оказалось все просто и логично.
> оказалось все просто и логично.И что самое весёлое - абсолютно неправильно. Впрочем запусти да и увидишь :)
> И что самое весёлое - абсолютно неправильно. Впрочем запусти да и увидишь
> :)ну по крайней мере дерево из 700+ каталогов, то есть 700+ строк в массив записалось, прочиталось.
при нужде удалилось, добавилось. без ошибок и каких-либо видимых косяков.
может стоит все же подробнее описывать, в чем человек не прав, а не строить из себя "мистер_я_лучше_Вас"? Уж простите.
>[оверквотинг удален]
> else
> {
> mass_size = mass_size +
> strlen(str);
> mass = (char**)realloc(mass, mass_size);
> }
> ...
> mass[num] = (char *)malloc(sizeof(str));
> }
> оказалось все просто и логично.Ваше первое решение было бессмыссленным
char *mass[]; - в области статитеских данных компилятор определил указатель на массив разменом в один элемент. При этом, скорее всего, выдал предупреждение, которое вы проигнорировали.
после этого mass[1] уже обращается к мусору. Удивительно, что программа вообще как-то работала.
Вам бы помогло
char (*mass)[]; или char **mass;
но этом случае память нужно выделять и под сам mass, и под стороки.Во втором случат память вы выделяете дважды и к мусору (в том случае, если длины строк больше длин указателей) не обращаетесь, но программа тем не менее абсолютно безграмотна, так как при коротких строках может выдать тот же сегментэйшин фаулт, а при длинных выделяет памяти почти вдвое больше, чем нужно.
Советую вам либо серьезнее отнестись к изучению основ языка C, либо подобрать другой язык, напритер Питон или Яву.
> оказалось все просто и логично.Оно точно работает?
Спасибо Анониму за подробное описание фейлов.
как я понял, закосячил я в выделении памяти под массив указателей.
Нужно в mass выделять память для указателей, а уже в mass[X] выделять память под строку.
Итог получился такой.char** mass;
int mass_cnt = 1; // количество строк (указателей)
...
int new_mass_str(char* str, int num)
{
if (mass == NULL)
{
mass = (char**) malloc(mass_cnt*sizeof(char *));
}
else
{
mass = (char**)realloc(mass, ++mass_cnt*sizeof(char *));
}
...
mass[num] = (char *)malloc(strlen(str)+1); // вот тут я в предыдущем варианте опечатался
// strlen конечно же
}Работает, памяти жрет намного меньше (для 715 строк уменьшение почти в 9 раз).
Где-то я опять закосячил?
> Спасибо Анониму за подробное описание фейлов.Правильное восприятие критики обнадеживает.
> Где-то я опять закосячил?
На этот раз практически все верно, если я чего не пропустил.
Еще бы:
1. Инициализировать mass нулем.
2. Проверять ошибки.
3. Реаллок делать не для каждой строки, а память добавлять кусками, допустип, сторок по 256.
4. Вместо глобальных переменных использовать статическую структуру внутри функции.
...
То уже почти библиотечная реализация.А если в задаче разрешено использовать C++, то в stl можно найти почти готовое решение.
В догонку.
Непонятно, зачем передавать функции номер строки, если есть глобальный счетчик.
>[оверквотинг удален]
> Еще бы:
> 1. Инициализировать mass нулем.
> 2. Проверять ошибки.
> 3. Реаллок делать не для каждой строки, а память добавлять кусками, допустип,
> сторок по 256.
> 4. Вместо глобальных переменных использовать статическую структуру внутри функции.
> ...
> То уже почти библиотечная реализация.
> А если в задаче разрешено использовать C++, то в stl можно найти
> почти готовое решение.mass нулем и обработку ошибок уже сделал (с работы нет постоянного доступа, поэтому тут набегами =) )
вот с добавлением кусками проблема. ftw() идет вниз по дереву иерархии и возвращает имена файлов и директорий. каждую директорию я сразу же начинаю отслеживать inotify'ем, и поэтому сразу добавляю ее в массив по номеру дескриптора. пока быстродействие инициализации не критично. когда доделаю полный функционал, там уже оптимизировать начну.спасибо за помощь
> mass нулем и обработку ошибок уже сделал (с работы нет постоянного
> доступа, поэтому тут набегами =) )
> вот с добавлением кусками проблема. ftw() идет вниз по дереву иерархии
> и возвращает имена файлов и директорий. каждую директорию я сразу же
> начинаю отслеживать inotify'ем, и поэтому сразу добавляю ее в массив по
> номеру дескриптора. пока быстродействие инициализации не критично. когда доделаю полный
> функционал, там уже оптимизировать начну.
> спасибо за помощьВам бы врачем работать или адвокатом. Много, умно, и не по теме (это про массив строк неизвестной длины).
ЗЫ Прочитал название темы, на полке прямо передо мной Хээфилд и проч. лежит. Последнее сообщение просто убило. Ну, понятно, что если бы всю тему прочитал, то наверное понял бы. Но тут слишком эээ... "жесть"...