Re[2]: invalid fastbin entry (free):
От: Ovoshlook  
Дата: 18.04.14 18:37
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Ovoshlook, Вы писали:


O>>Исходный код формирования структуры MAPPER вот такой (printf для теста. можно не обращать внимание):


К>Такое впечатление, что этот код был переписан с паскаля. Индекс от 1 до colls_num включительно, проверка нечётности (!!!), и т.п.

К>Можно я его просто начисто перепишу?
К>
К>MAPPER make_mapper(SPLITTER *splitter)
К>{
К>    MAPPER mapper;
К>    int i;

К>    mapper.colls_num = splitter->colls_num / 2; /* сразу знаем количество */
К>    mapper.name  = (char**) malloc(mapper.colls_num * sizeof(char*));
К>    mapper.value = (char**) malloc(mapper.colls_num * sizeof(char*));

К>    for(i=0; i<mapper.colls_num; ++i)
К>    {
К>        mapper.name [i] = strdup(splitter->substrings[i*2  ]); /* не морочим себе голову, берём стандартную функцию аллокации строк */
К>        mapper.value[i] = strdup(splitter->substrings[i*2+1]);
К>    }

К>    return mapper;
К>}
К>

К>Это если помещать каждую строку в отдельный блок.
К>А если хочется разместить все данные в одном блоке, чтобы mapper.name указывал на таблицу индексов, откуда ссылки вели бы на строки в этом же блоке, то НЕЛЬЗЯ делать realloc.
К>Потому что ты, тем самым, сбиваешь все указатели, которые были внутрь старого блока.

К>Делаем более чисто:

К>
К>char* putback(char* /*in-out*/ *pblock, char const* str)
К>{
К>    char* block = *pblock;
К>    int size;
К>    size = strlen(str) + 1;

К>    strcpy(block, str); /* копируем строку */
К>    (*pblock) += size; /* двигаем указатель начала блока */
К>    return block; /* возвращаем адрес копии */
К>}

К>MAPPER make_mapper(SPLITTER *splitter)
К>{
К>    MAPPER mapper;
К>    int n, i;
К>    int len_names, len_values;
К>    char* block_names;
К>    char* block_values;

К>    n = splitter->colls_num / 2;

К>    /* считаем потребную память */
К>    len_names = 0;
К>    len_values = 0;
К>    for(i=0; i<n; ++i)
К>    {
К>        len_names  += strlen(splitter->substrings[i*2  ]) + 1; /* включая концевые нули */
К>        len_values += strlen(splitter->substrings[i*2+1]) + 1;
К>    }

К>    /* выделяем память */
К>    block_names  = (char*) malloc(n*sizeof(char*) + len_names *sizeof(char));
К>    block_values = (char*) malloc(n*sizeof(char*) + len_values*sizeof(char));

К>    /* настраиваем структуру */
К>    mapper.colls_num = n;
К>    mapper.name  = (char**) block_names;  block_names  += n*sizeof(char*);
К>    mapper.value = (char**) block_values; block_values += n*sizeof(char*);

К>    /* копируем строки */
К>    for(i=0; i<n; ++i)
К>    {
К>        mapper.name [i] = putback(&block_names,  splitter->substrings[i*2  ]);  
К>        mapper.value[i] = putback(&block_values, splitter->substrings[i*2+1]);
К>    }

К>    return mapper;
К>}
К>


Огромное спасибо, хотя не совсем понятно почему нельзя использовать Realloc при выделении добавлении нового участка памяти к уже созданному массиву в динамике.
Re[16]: invalid fastbin entry (free):
От: Ovoshlook  
Дата: 18.04.14 18:42
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, Ovoshlook, Вы писали:


O>>>>Чтобы положить в нее свое значение

EP>>>Откуда? из arr->substrings[i-1]?
EP>>>То есть тебе нужно скопировать стоку, первый символ которой находится по адресу arr->substrings[i-1], в строку, первый символ которой находится по адресу string?
EP>>>Как именно ты собрался это делать?
O>>map.name[k]=arr->substrings[i-1];

EP>Тут происходит копирование адреса, а не самой строки. Причём тот адрес который был раньше слева — затирается.


EP>P.S. По всей видимости ты только начинаешь изучение C. Если в дальнейшем планируешь перейти на C++, то нет никакой необходимости сначала учить C — это только привьёт вредные привычки, которые к тому же порождают тормозной код.

EP>Советую начать с книги Страуструпа — Programming -- Principles and Practice Using C++ (или на русском).

Да. Я в курсе что передастся адрес на начало строки. Но собственно это и нужно- чтобы не плодить копии одной и той же строки. Да, с С я недавно познакомился и очень интересует именно работа с памятью, многопоточность, минималистичность и тому подобное. Естественно 1 блин комом, но поэтому сюда и обращаюсь, чтобы как не оставлять пробелов и понять недостающее. С С++ пока что не намерен связываться, хотя раньше писал дипломный проект на нем, точнее на Qt, все таки там очень высокоуровневое все, поэтому база не большая. За ссылку отдельное спасибо тем не менее.
Re[17]: invalid fastbin entry (free):
От: Evgeny.Panasyuk Россия  
Дата: 18.04.14 20:12
Оценка:
Здравствуйте, Ovoshlook, Вы писали:

O>Да. Я в курсе что передастся адрес на начало строки. Но собственно это и нужно- чтобы не плодить копии одной и той же строки.


Ок, но если не нужны копии — тогда для чего выделять буфер размером со строку?

O>Да, с С я недавно познакомился и очень интересует именно работа с памятью, многопоточность, минималистичность и тому подобное.


Если сравнивать минималистичность самих языков, то тут безусловно лидирует C.
Если же сравнивать минималистичность кода, то C++ превосходит C. То есть сам код получается более лаконичный и быстрый (Это одна из основных фишек C++. Для многих это даже контринтуитивно, т.е. существует стереотип, что быстрый код должен быть dirty/hacky и super low-level, C++ как раз опровергает это).
Вот, например, что говорит Александр Степанов, создатель STL:

What do I mean when I say that an algorithm does not "impose any performance penalty"? In other words, how do you know that a generic algorithm is efficient? An algorithm is called relatively efficient if it's as efficient as a nongeneric version written in the same language, and it's called absolutely efficient if it's as efficient as a nongeneric assembly language version.

For many years, I tried to achieve relative efficiency in more advanced languages (e.g., Ada and Scheme) but failed. My generic versions of even simple algorithms were not able to compete with built-in primitives. But in C++ I was finally able to not only accomplish relative efficiency but come very close to the more ambitious goal of absolute efficiency. To verify this, I spent countless hours looking at the assembly code generated by different compilers on different architectures.

Re[3]: invalid fastbin entry (free):
От: Кодт Россия  
Дата: 18.04.14 22:12
Оценка:
Здравствуйте, Ovoshlook, Вы писали:

O>Огромное спасибо, хотя не совсем понятно почему нельзя использовать Realloc при выделении добавлении нового участка памяти к уже созданному массиву в динамике.


Можно, но с пониманием.
realloc не просто увеличивает память, но и перемещает её, соответственно, все указатели внутрь старого блока становятся невалидными.
Кстати говоря, твой исходный код содержит характерные ошибки, показывающие существенное непонимание работы с памятью и со строками в Си.
После паскаля (или бейсика?) надо обязательно переучиваться, там всё совсем по-другому.

Например,
j = strlen(arr->substrings[i]);
...
map.name = realloc(map.name, sizeof(char*)*j + 1);

По задумке, хотелось добавить к массиву name ещё немножко памяти под очередную строку.
По факту, старый размер забыт, а память выделена только под неё.

Надо было писать
size_t bufsize;
char* buffer;

size_t count;
size_t* offsets;
char** strings; /* неправильно */

.....
size_t len = strlen(s);

buffer = realloc(buffer, (size+len+1)*sizeof(char)); /* изменили буфер */
offsets = realloc(offsets, (count+1)*sizeof(size_t)); /* изменили массивы индексов */
strings = realloc(strings, (count+1)*sizeof(char*));

offsets[count] = size; /* запомнили начало новой строки - её позицию... */
strings[count] = buffer+size; /* и непосредственно указатель на неё */

strcpy(buffer+size, s); /* скопировали строку внутрь буфера - в хвост */

count++;
size += len+1;

.....
/* получаем i-ю строку */
char* t = buffer + offsets[i]; /* правильно */
char* e = strings[i]; /* неправильно */

В чём проблема: после realloc смещения останутся теми же самыми (их надо будет отсчитывать от начала нового буфера), а вот указатели в массиве strings — все, кроме последнего, будут направлены в потолок.

Но в одном посте это всё рассказывать — никаких сил не будет.
Так что — бери старых добрых Кернигана и Ричи, и читай.
Перекуём баги на фичи!
Re[4]: invalid fastbin entry (free):
От: Ovoshlook  
Дата: 19.04.14 17:22
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Ovoshlook, Вы писали:


O>>Огромное спасибо, хотя не совсем понятно почему нельзя использовать Realloc при выделении добавлении нового участка памяти к уже созданному массиву в динамике.


К>Можно, но с пониманием.

К>realloc не просто увеличивает память, но и перемещает её, соответственно, все указатели внутрь старого блока становятся невалидными.
К>Кстати говоря, твой исходный код содержит характерные ошибки, показывающие существенное непонимание работы с памятью и со строками в Си.
К>После паскаля (или бейсика?) надо обязательно переучиваться, там всё совсем по-другому.

К>Например,

К>
К>j = strlen(arr->substrings[i]);
К>...
К>map.name = realloc(map.name, sizeof(char*)*j + 1);
К>

К>По задумке, хотелось добавить к массиву name ещё немножко памяти под очередную строку.
К>По факту, старый размер забыт, а память выделена только под неё.

К>Надо было писать

К>
К>size_t bufsize;
К>char* buffer;

К>size_t count;
К>size_t* offsets;
К>char** strings; /* неправильно */

К>.....
К>size_t len = strlen(s);

К>buffer = realloc(buffer, (size+len+1)*sizeof(char)); /* изменили буфер */
К>offsets = realloc(offsets, (count+1)*sizeof(size_t)); /* изменили массивы индексов */
К>strings = realloc(strings, (count+1)*sizeof(char*));

К>offsets[count] = size; /* запомнили начало новой строки - её позицию... */
К>strings[count] = buffer+size; /* и непосредственно указатель на неё */

К>strcpy(buffer+size, s); /* скопировали строку внутрь буфера - в хвост */

К>count++;
К>size += len+1;

К>.....
К>/* получаем i-ю строку */
К>char* t = buffer + offsets[i]; /* правильно */
К>char* e = strings[i]; /* неправильно */
К>

К>В чём проблема: после realloc смещения останутся теми же самыми (их надо будет отсчитывать от начала нового буфера), а вот указатели в массиве strings — все, кроме последнего, будут направлены в потолок.

К>Но в одном посте это всё рассказывать — никаких сил не будет.

К>Так что — бери старых добрых Кернигана и Ричи, и читай.

Спасибо за разжевывания. Теперь более понятно. Обязательно прочту
Re[18]: invalid fastbin entry (free):
От: Ovoshlook  
Дата: 19.04.14 17:30
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:



EP>Ок, но если не нужны копии — тогда для чего выделять буфер размером со строку?


Наверное просто можно скопировать адрес строки в новый массив и все..ю Действительно...

O>>Да, с С я недавно познакомился и очень интересует именно работа с памятью, многопоточность, минималистичность и тому подобное.


EP>Если сравнивать минималистичность самих языков, то тут безусловно лидирует C.

EP>Если же сравнивать минималистичность кода, то C++ превосходит C. То есть сам код получается более лаконичный и быстрый (Это одна из основных фишек C++. Для многих это даже контринтуитивно, т.е. существует стереотип, что быстрый код должен быть dirty/hacky и super low-level, C++ как раз опровергает это).

Ну помимо прочего, есть некое ПО написанное на С которое мне нужно бы расширить в будущем, поэтому и С. + Идеология классов меня не совсем устраивает, а если в С++ не использовать классы, то зачем использовать С++? (ну это как бы вопрос а не опровержение). Хотя конечно по поводу скорости (самого кода в итоге) — наверное это хороший аргумент в сторону С++, но как мне кажется хорошая программа на С не будет уступать С++ учитывая что С часто используют в программах, которые должны обрабатывать realtime потоки данных и подобные вещи. Но это уже риторика. Спасибо за подсказки и помощь. Буду делать и добиваться результата.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.