Автор: MmM , 17 июля 2006
вот мучаю такую конструкцию(кусок плугина к миранде, который позволяет сохранять и поднимать контакт-лист в удобоваримом виде):

[code:1]void createParentGroups(const char *groupName)
{
if ( strrchr(groupName,'\\') != NULL )
{
char *duplicate;
duplicate = strdup(groupName);
if( duplicate == NULL )
MessageBox(NULL, Translate("Insufficient memory available"), Translate("Error"),MB_OK);
else
{
char *pos;
pos = strrchr(duplicate,'\\'); //Find the last \ character
if (pos != NULL)
{
*pos = 0; // Nullterminate the string where the last \ was found
createGroup(duplicate);
}
else
{
MessageBox(NULL, Translate("A critical error occured.\nTry to do the operation one more time."), Translate("Critical error"),MB_OK);
}
}
free( duplicate ); //Since strdup calls malloc it is good to free the space allocated
}

return;
}


void createGroup(const char *groupName)
{
if (!groupExistsOLD(groupName))
{
int groupId;
char groupIdStr[11];
DBVARIANT dbv;
char *groupName2;
createParentGroups(groupName); // Create the parentgroups if needed
groupName2 = malloc(strlen(groupName + 2));
groupName2[0] = 1; // This is because the DB requires the groupname to begin with the second character in the string
groupName2[1] = 0;
strcat(groupName2, groupName);
// Find the right id for the group
for(groupId = 0;; groupId++)
{
itoa(groupId, groupIdStr,10);
if(DBGetContactSetting(NULL, "CListGroups", groupIdStr, &dbv))
break;
DBFreeVariant(&dbv);
}
DBWriteContactSettingString(NULL,"CListGroups", groupIdStr, groupName2);
free( groupName2 );
}
return;
}
[/code:1]

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

Группа передается в аргументах в виде Жилкомсбыт\По работе с физическими лицами отдел

... эта конструкция виснет на второй итерации при попытке выполнить free( groupName2 ); ...

... закоментил, откомпилил ... на машине с двумя гигами оперативы пашет замечательно ... на 256 - вылетает после создания первой группы (но первую - создает)

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

Добавлено спустя 1 час 30 минут 54 секунды:

Вроде нашел косяк ... только не совсем понятно, почему оно начало работать ... поменял
[code:1]
groupName2 = malloc(strlen(groupName + 2));
[/code:1]
на
[code:1]
groupName2 = malloc(strlen(groupName) + 2);
[/code:1]
Содержимое данного поля является приватным и не предназначено для показа.

BBCode

  • HTML-теги не обрабатываются и показываются как обычный текст
  • You may use the following BBCode tags:
    • [align]
    • [b]
    • [code]
    • [color]
    • [font]
    • [hr]
    • [i]
    • [img]
    • [list]
    • [quote]
    • [s]
    • [size]
    • [spoiler]
    • [sub]
    • [sup]
    • [table]
    • [u]
    • [url]
  • Адреса веб-страниц и email-адреса преобразовываются в ссылки автоматически.

Root

19 лет 7 месяцев назад

[code:1]groupName2 = malloc(strlen(groupName + 2));[/code:1]
дык. потому что тута берется кусок от groupName, начиная с третьего символа...
а тута:
[code:1]groupName2 = malloc(strlen(groupName) + 2);[/code:1]
просто резервируется кусок памяти размером длина groupName + 2 байта
хотя, наверное, это будет еще корректнее:
[code:1]groupName2 = malloc(strlen(groupName + 2) + 2);[/code:1]
но точно не уверен

Unknown BIOS (не проверено)

19 лет 7 месяцев назад

[code:1]
groupName2 = malloc(strlen(groupName + 2));
[/code:1]
Странная конструкция, для ф-ии strlen дается строка groupName начиная с 3-го символа. А если в groupName лежит строка длиной в 1 символ? Тогда strlen попрет по памяти в поисках 0, возможно найдет его где-то, и возвратит какое-то число, именно на это число байт и попытается выделить память malloc.
Верный вариант конечно этот:
[code:1]
groupName2 = malloc(strlen(groupName) + 2);
[/code:1]

Root

19 лет 7 месяцев назад

dimm
фишка в том, что ниже там же написано:
[code:1] groupName2[0] = 1; // This is because the DB requires the groupname to begin with the second character in the string
groupName2[1] = 0;[/code:1]
т.е. содержательная часть groupName начинается с третьего символа, а первые два символы с кодами 0x01 и 0x00. Вот меня волнует вопрос - а не споткнется ли strlen тута (т.е. напишет, что строка "всего лишь" 2 символа)... Мы ж то не знаем 100%, что же в эту функцию передается :roll:
так что имхо:
[code:1]groupName2 = malloc(strlen(groupName + 2) + 2);[/code:1]
т.е. подсчитать длину содержательной части groupName + добавить два резервных байта...

Unknown BIOS (не проверено)

19 лет 7 месяцев назад

Нет,
[code:1]
groupName2 = malloc(strlen(groupName + 2) + 2);
[/code:1]
неверно! При groupName состоящей из 1 символа strlen() вернет неизвестно что.
Вообще правильно вот так:
[code:1]
groupName2 = malloc(strlen(groupName) + 1);
[/code:1]
так как там в комментарии подписано:
[code:1]
groupName2[0] = 1; // This is because the DB requires the groupname to begin with the second character in the string
groupName2[1] = 0;
[/code:1]
т.е. DB требует, чтобы groupname начинался со второго символа, поэтому они в первый пихают 1, затем сразу 0, т.е. длину строки делают = 1. А затем вызывают strcat() - которая объединяет 2 строки:
[code:1]
strcat(groupName2, groupName);
[/code:1]
т.е. в строку groupName2 добавляют содержимое строки groupName, таким образом длина строки groupName2 должна быть на 1 больше чем groupName, т.к. в начале записана 1.

Root

19 лет 7 месяцев назад

groupName2 = malloc(strlen(groupName) + 1);

убедили :lol: почти. Только теперь меня берут сомнения:
у нас strlen возвращает длину строки без \0. Т.е. длина groupName2=длина groupName + 1 (на "\0") + 1 (и на 1-ку в самом начале)
так что правильный вариант:
groupName2 = malloc(strlen(groupName) + 2);

Unknown BIOS (не проверено)

19 лет 7 месяцев назад

Ага, точно, прогнал, забыл про strlen() и \0 :)

MmM

19 лет 7 месяцев назад

Тоесть получается, что я то какраз все верно нашел ... кул.