Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Visual C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 29.03.2012, 08:40   #1
RomanA
Пользователь
 
Регистрация: 10.08.2011
Сообщений: 30
По умолчанию Ошибка при очистке памяти (язык Си): The pointer MUST come from the 'local' heap

Пишу на Microsoft Visual C++ 2010 Express. Файл с расширение .c, что позволяет компилятору интерпретировать код как написанный на языке Си.

Функция conc - функция с переменным числом параметров (признак окончания списка параметров - NULL). Объединяет строки в одну и возвращает указатель на объединенную строку. Объединенная строка создается в динамической памяти.

main - динамически выделяет память под три строки, считывает их, выводит на экран и освобождает память.

Программа вроде бы работает нормально, но на этапе очистки памяти в main (строка free(RS); ) возникает ошибка:

Цитата:
ОС Windows инициировала точку останова в Lab4.exe.

Это может быть вызвано повреждением кучи и указывает на ошибку в Lab4.exe или в одной из загруженных им DLL.

Возможной причиной так же может быть нажатие пользователем клавиши F12, когда фокус принадлежит Lab4.exe

Выведенное на экран окно содержит дополнительные данные для диагностики ошибки
Перебрасывает в файл dbgheap.c на строки:

Цитата:
/*
* If this ASSERT fails, a bad pointer has been passed in. It may be
* totally bogus, or it may have been allocated from another heap.
* The pointer MUST come from the 'local' heap.
*/
_ASSERTE(_CrtIsValidHeapPointer(pUs erData));
Не совсем понимаю, почему выдается ошибка. Не может же быть причиной то, что я выделил память в одной функции, а освобождаю в другой?

Вот код:
Код:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_STRING_SIZE 20

char* conc(char* S1, ... )
{
//Definiton variables
	char* ConcString = NULL;      //Dynamic string for result
	char** p = &S1;               //Ponter on array of strings
	unsigned int Size;            //Size of first string

//Test data
	if(S1 == NULL) return NULL;

//Copy S1 in ConcString
	Size = strlen(S1);
	ConcString = (char*)realloc(ConcString,sizeof(char)*Size);
	strcpy(ConcString,S1);
	p++;

//Concatenation
	while((*p) != NULL)
	{
		strcat(ConcString,(*p));
		p++;
	}

//Return result
	return ConcString;
}

void main()
{
//Definition variables
	char Buf[MAX_STRING_SIZE];
	char *RS = NULL;
	char **ArrStr = (char**)malloc(sizeof(char*)*3);
	unsigned int i, Size;

//Input data
	for(i = 0; i < 3; i++)
	{
		fflush(stdin); printf("Input %u tring (max size is %u): ",i,MAX_STRING_SIZE);
		fgets(Buf,MAX_STRING_SIZE,stdin);
		Size = strlen(Buf); Buf[Size-1]=Buf[Size];
		ArrStr[i] = (char*)malloc(sizeof(char)*Size);
		strcpy(ArrStr[i],Buf);
	}

//Concatenation of string
	RS = conc(ArrStr[0],ArrStr[1],ArrStr[2],NULL);

//Output results
	printf("Result of concatenation is: %s",RS);
	getch();
	
//Free memory
	for(i = 0; i < 3; i++)
	{
		free(ArrStr[i]);
	}
	free(ArrStr);
	free(RS);  //ОШИБКА!
}
Может быть кто понимает в чем моя проблема?

Последний раз редактировалось RomanA; 29.03.2012 в 08:45.
RomanA вне форума Ответить с цитированием
Старый 29.03.2012, 09:09   #2
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Потому что Вы выделили буфер в памяти длиной равной длине первой строки и после в него добавляете данные еще из двух других.
Код:
//....
unsigned int Size = strlen(S1);
ConcString = (char*)realloc(ConcString,sizeof(char)*Size);
//...
while((*p) != NULL)
	{
	strcat(ConcString,(*p));
//...
Маловат буфер однако...
EUGY вне форума Ответить с цитированием
Старый 29.03.2012, 09:29   #3
RomanA
Пользователь
 
Регистрация: 10.08.2011
Сообщений: 30
По умолчанию

Хех... подправил цикл:

Код:
	while((*p) != NULL)
	{
		Size += strlen(*p);
		ConcString = (char*)realloc(ConcString,sizeof(char)*Size);
		strcat(ConcString,(*p));
		p++;
	}
Ошибка с очисткой памяти исчезла.
Но началось что-то странное: если на входе три строки "qwe", "asd", "zxc", то на выходе получается строка: "qwe══════¤¤¤¤ллллллллzxc" O_o

Модифицировал код функции полностью:

Код:
char* conc(char* S1, ... )
{
//Definiton variables
	char* ConcString = NULL;      //Dynamic string for result
	char** p = &S1;               //Ponter on array of strings
	unsigned int Size;            //Size of first string

//Test data
	if(S1 == NULL) return NULL;

//Size
	Size = strlen(S1);
	p++;

	while((*p) != NULL) {Size+=strlen(*p); p++;}
	p = &S1;

	ConcString = (char*)realloc(ConcString,sizeof(char)*Size);

//Concatenation
	while((*p) != NULL)
	{
		strcat(ConcString,(*p));
		p++;
	}

//Return result
	return ConcString;
}
Если на входе три строки "qwe", "asd", "zxc", то на выходе получается строка: "═════════¤¤¤¤лллллллл■ю■qweasdzxc" .

Хотя в этом случае выдает ту же ошибку, но уже посылает на другой кусок файла dbgheap.c:

Код:
        __try {
            /* allocate the block
             */
            _free_dbg_nolock(pUserData, nBlockUse);
        }
Вообще не понимаю что происходит O_o. Какое-то странное выделение памяти делает realloc (malloc кстати тоже).

Последний раз редактировалось RomanA; 29.03.2012 в 09:51.
RomanA вне форума Ответить с цитированием
Старый 29.03.2012, 09:48   #4
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Если Вы пишите не в блокноте, то все нормальные IDE могут останавливать выполнение дебажного кода в точке останова.
Вот и остановите выполнение на вызове conc(... и пошагово пройдите все инструкции, отслеживая состояние всех переменных. Работайте!
EUGY вне форума Ответить с цитированием
Старый 29.03.2012, 09:59   #5
RomanA
Пользователь
 
Регистрация: 10.08.2011
Сообщений: 30
По умолчанию

В том то и дело, что прохожу.
malloc вместо 10 выделяет 24 байта... >_< Это вообще возможно???

RomanA вне форума Ответить с цитированием
Старый 29.03.2012, 10:10   #6
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

На основании чего Вы решили что malloc/realloc выделяет больше памяти?
Уж не на основании ли того, что сразу после выделения памяти пробегаетесь по буферу функцией strlen и считаете ее возвращаемое значение длиной выделенного буфера?
Она ведь при этом может вернуть все, что душе угодно. До первого встретившегося нуля в неинициализированной памяти. Учли это?

PS. если проверить длину выделенного через malloc/realloc/calloc, то надо через _msize

Последний раз редактировалось EUGY; 29.03.2012 в 10:14.
EUGY вне форума Ответить с цитированием
Старый 29.03.2012, 10:16   #7
RomanA
Пользователь
 
Регистрация: 10.08.2011
Сообщений: 30
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
На основании чего Вы решили что malloc/realloc выделяет больше памяти?
Уж не на основании ли того, что сразу после выделения памяти пробегаетесь по буферу функцией strlen и считаете ее возвращаемое значение длиной выделенного буфера?
Она ведь при этом может вернуть все, что душе угодно. До первого встретившегося нуля в неинициализированной памяти. Учли это?

PS. если проверить длину выделенного через malloc/realloc/calloc, то надо через _msize
Ой..дааа)) Жуткую глупость сотворил.

Спасибо большое, что тратите время на такого идиота как я)))
Вставил строку ConcString[0] = '\0'; после выделения памяти и все заработало без ошибок!
RomanA вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при очистке памяти alexey_kip Visual C++ 3 12.02.2012 11:55
ошибка Edit при очистке значения Backspace-ом voverrr Общие вопросы Delphi 14 08.02.2011 09:27
Модуль Local.h в C++/Интересует Русский язык ISV-777 Помощь студентам 1 10.11.2010 20:08
Ошибка доступа памяти, при работе с принятой строкой. Zeraim Работа с сетью в Delphi 11 26.01.2010 01:11
Ошибка при очистке динамического массива. S_Yevgeniy Помощь студентам 4 24.12.2009 18:45