вот мучаю такую конструкцию(кусок плугина к миранде, который позволяет сохранять и поднимать контакт-лист в удобоваримом виде):
[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]
дык. потому что тута берется кусок от groupName, начиная с третьего символа...
а тута:
[code:1]groupName2 = malloc(strlen(groupName) + 2);[/code:1]
просто резервируется кусок памяти размером длина groupName + 2 байта
хотя, наверное, это будет еще корректнее:
[code:1]groupName2 = malloc(strlen(groupName + 2) + 2);[/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]
фишка в том, что ниже там же написано:
[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 + добавить два резервных байта...
[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.
убедили :lol: почти. Только теперь меня берут сомнения:
у нас strlen возвращает длину строки без \0. Т.е. длина groupName2=длина groupName + 1 (на "\0") + 1 (и на 1-ку в самом начале)
так что правильный вариант: