The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Массив строк неизвестной длины"
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (C/C++)
Изначальное сообщение [ Отслеживать ]

"Массив строк неизвестной длины"  +/
Сообщение от trmt (ok) on 23-Сен-12, 17:54 
Доброго времени суток.
Нужно описать массив неизвестного количества строк неизвестной длины в Си.

Пока имею следующее решение (код примерный, так как он на рабочем компе)
/* Глобальная переменная*/
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]).
Если есть какие-то еще варианты - буду рад выслушать. Но решение вопроса о массиве тоже хотелось бы узнать.

Заранее благодарен.

Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Массив строк неизвестной длины"  +/
Сообщение от pavlinux (ok) on 24-Сен-12, 04:42 
> Доброго времени с уток.

1. Пока не напишешь своей ОС, не юзай указатели на массивы!
2. sizeof(char *str) == SIZE_OF_CHAR

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Массив строк неизвестной длины"  +/
Сообщение от trmt (ok) on 24-Сен-12, 04:55 
>> Доброго времени с уток.
> 1. Пока не напишешь своей ОС, не юзай указатели на массивы!
> 2. sizeof(char *str) == SIZE_OF_CHAR

Опс, извиняюсь

не так написал.
...
    mass[num] = (char *) malloc (strlen(str));
...

Ответить | Правка | ^ к родителю #1 | Наверх | Cообщить модератору

3. "Массив строк неизвестной длины"  +/
Сообщение от pavlinux (ok) on 24-Сен-12, 05:15 
> Опс, извиняюсь, не так написал.

Тут много полезного
http://faqs.org.ru/progr/c_cpp/cfaqrus.htm

Ответить | Правка | ^ к родителю #2 | Наверх | Cообщить модератору

4. "Массив строк неизвестной длины"  +/
Сообщение от trmt (ok) on 24-Сен-12, 07:02 
>[оверквотинг удален]
> 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));
}

оказалось все просто и логично.


Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

5. "Массив строк неизвестной длины"  +/
Сообщение от Аноним (??) on 24-Сен-12, 08:45 
> оказалось все просто и логично.

И что самое весёлое - абсолютно неправильно. Впрочем запусти да и увидишь :)


Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

6. "Массив строк неизвестной длины"  +/
Сообщение от trmt (ok) on 24-Сен-12, 18:14 
> И что самое весёлое - абсолютно неправильно. Впрочем запусти да и увидишь
> :)

ну по крайней мере дерево из 700+ каталогов, то есть 700+ строк в массив записалось, прочиталось.
при нужде удалилось, добавилось. без ошибок и каких-либо видимых косяков.
может стоит все же подробнее описывать, в чем человек не прав, а не строить из себя "мистер_я_лучше_Вас"? Уж простите.


Ответить | Правка | ^ к родителю #5 | Наверх | Cообщить модератору

7. "Массив строк неизвестной длины"  +/
Сообщение от Аноним (??) on 24-Сен-12, 20:39 

>[оверквотинг удален]
>     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, либо подобрать другой язык, напритер Питон или Яву.

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

8. "Массив строк неизвестной длины"  +/
Сообщение от pavlinux (ok) on 24-Сен-12, 22:35 
> оказалось все просто и логично.

Оно точно работает?

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

9. "Массив строк неизвестной длины"  +/
Сообщение от trmt (ok) on 25-Сен-12, 11:48 
Спасибо Анониму за подробное описание фейлов.
как я понял, закосячил я в выделении памяти под массив указателей.
Нужно в 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 раз).

Где-то я опять закосячил?

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

10. "Массив строк неизвестной длины"  +/
Сообщение от Аноним (??) on 25-Сен-12, 18:56 
> Спасибо Анониму за подробное описание фейлов.

Правильное восприятие критики обнадеживает.

> Где-то я опять закосячил?

На этот раз практически все верно, если я чего не пропустил.
Еще бы:
1. Инициализировать mass нулем.
2. Проверять ошибки.
3. Реаллок делать не для каждой строки, а память добавлять кусками, допустип, сторок по 256.
4. Вместо глобальных переменных использовать статическую структуру внутри функции.
...
То уже почти библиотечная реализация.

А если в задаче разрешено использовать C++, то в stl можно найти почти готовое решение.

Ответить | Правка | ^ к родителю #9 | Наверх | Cообщить модератору

11. "Массив строк неизвестной длины"  +/
Сообщение от Аноним (??) on 25-Сен-12, 19:06 
В догонку.
Непонятно, зачем передавать функции номер строки, если есть глобальный счетчик.
Ответить | Правка | ^ к родителю #10 | Наверх | Cообщить модератору

12. "Массив строк неизвестной длины"  +/
Сообщение от trmt (ok) on 25-Сен-12, 19:12 
>[оверквотинг удален]
> Еще бы:
> 1. Инициализировать mass нулем.
> 2. Проверять ошибки.
> 3. Реаллок делать не для каждой строки, а память добавлять кусками, допустип,
> сторок по 256.
> 4. Вместо глобальных переменных использовать статическую структуру внутри функции.
> ...
> То уже почти библиотечная реализация.
> А если в задаче разрешено использовать C++, то в stl можно найти
> почти готовое решение.

mass нулем и обработку  ошибок уже сделал (с работы нет постоянного доступа, поэтому тут набегами =) )
вот  с добавлением кусками проблема. ftw() идет вниз по дереву иерархии и возвращает имена файлов и директорий. каждую директорию я сразу же начинаю отслеживать inotify'ем, и поэтому сразу добавляю ее в массив по номеру дескриптора. пока быстродействие инициализации не критично. когда доделаю полный функционал, там уже оптимизировать начну.

спасибо за помощь


Ответить | Правка | ^ к родителю #10 | Наверх | Cообщить модератору

13. "Массив строк неизвестной длины"  +/
Сообщение от Andrey (??) on 29-Сен-12, 18:55 

> mass нулем и обработку  ошибок уже сделал (с работы нет постоянного
> доступа, поэтому тут набегами =) )
> вот  с добавлением кусками проблема. ftw() идет вниз по дереву иерархии
> и возвращает имена файлов и директорий. каждую директорию я сразу же
> начинаю отслеживать inotify'ем, и поэтому сразу добавляю ее в массив по
> номеру дескриптора. пока быстродействие инициализации не критично. когда доделаю полный
> функционал, там уже оптимизировать начну.
> спасибо за помощь

Вам бы врачем работать или адвокатом. Много, умно, и не по теме (это про массив строк неизвестной длины).

ЗЫ Прочитал название темы, на полке прямо передо мной Хээфилд и проч. лежит. Последнее сообщение просто убило. Ну, понятно, что если бы всю тему прочитал, то наверное понял бы. Но тут слишком эээ... "жесть"...


Ответить | Правка | ^ к родителю #12 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру