Кто у нас лихо на С лабает (часть2)

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

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;
}

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

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

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

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

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

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

Вроде нашел косяк ... только не совсем понятно, почему оно начало работать ... поменял

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

на
groupName2 = malloc(strlen(groupName) + 2); 

Аватар пользователя Root

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

Аццкий ромбовод {:€
Я пока не волшебник - я только учусь! :-P

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

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

Аватар пользователя Root

dimm
фишка в том, что ниже там же написано:

      groupName2[0] = 1; // This is because the DB requires the groupname to begin with the second character in the string 
      groupName2[1] = 0;

т.е. содержательная часть groupName начинается с третьего символа, а первые два символы с кодами 0x01 и 0x00. Вот меня волнует вопрос - а не споткнется ли strlen тута (т.е. напишет, что строка "всего лишь" 2 символа)... Мы ж то не знаем 100%, что же в эту функцию передается roll
так что имхо:
groupName2 = malloc(strlen(groupName + 2) + 2);
т.е. подсчитать длину содержательной части groupName + добавить два резервных байта...

Аццкий ромбовод {:€
Я пока не волшебник - я только учусь! :-P

Нет,

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

неверно! При groupName состоящей из 1 символа strlen() вернет неизвестно что.

Вообще правильно вот так:
groupName2 = malloc(strlen(groupName) + 1);

так как там в комментарии подписано:
groupName2[0] = 1; // This is because the DB requires the groupname to begin with the second character in the string 
groupName2[1] = 0;

т.е. DB требует, чтобы groupname начинался со второго символа, поэтому они в первый пихают 1, затем сразу 0, т.е. длину строки делают = 1. А затем вызывают strcat() - которая объединяет 2 строки:
strcat(groupName2, groupName);

т.е. в строку groupName2 добавляют содержимое строки groupName, таким образом длина строки groupName2 должна быть на 1 больше чем groupName, т.к. в начале записана 1.

Аватар пользователя Root

Цитата:
groupName2 = malloc(strlen(groupName) + 1);

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

Аццкий ромбовод {:€
Я пока не волшебник - я только учусь! :-P

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

Аватар пользователя MmM

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

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Разрешённые HTML-теги: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img>
  • You can use BBCode tags in the text. URLs will automatically be converted to links.

Подробнее о форматировании текста

Антибот - введите цифру.
Ленты новостей