Delete c выдает ошибку

Сначала вы динамически выделили память и ее адрес сохранили в переменной ptr

char *ptr = new char[len];

Затем вы изменили значение этой переменной, присвоив ей адрес памяти, занимаемой строковым литералом

ptr = str;

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

Затем вы попытались удалить память, занимаемую строковым литералом

delete[] ptr; // операция 

Однако строковые литералы хранятся в статической области памяти программы, а не в динамической. Вы не можете применять оператор delete []delete) к указателю, если он не хранит адрес памяти, выделенной динамически с помощью оператора new

Именно поэтому возникла ошибка.

Я думаю, что вы имели в виду следующее

#include <iostream>
#include <cstring>
#include <clocale>
using namespace std;


int main()
{
    setlocale(LC_CTYPE, "rus");

    const char* str = "heLLoWorld";
    size_t len = strlen( str );

    char *ptr = new char[len + 1];
    strcpy( ptr, str );

    cout << ptr << endl;

    delete[] ptr;
}

Обратите внимание, что функция strlen имеет тип возвращаемого значения size_t. Этот же тип имеет оператор-функция new для своего параметра, которая вызывается для выделения необходимой памяти.

Также строковые литералы в C++ имеют типы константных массивов. Поэтому указатели на символы строковых литералов также должны иметь квалификатор const.

Например

const char* str = "heLLoWorld";

Vlados_Bro,
Вообще, деструктор вызывается автоматически когда истекает «время жизни» объекта.
В зависимости от того каким образом объект был сформирован, это самое «время жизни» может меняться.

Например, для объекта, который сформирован в динамической памяти, деструктор сработает автоматически при применении delete к указателю на этот объект. То есть в таком случае без delete деструктор не вызывается.

Helpdes,
Класс не удаляется
Освобождается память которая выделена под объект.
Если объект использует динамические ресурсы внутри себя и эти данные никому после него не нужны, то надо освобождать эти ресурсы
иначе будет утечка памяти.

То есть программа работает, потребляет ресурсы но не возвращает их когда они больше не нужны.
Получается некая монополия, а ресурсы то ведь не бесконечны.

На дистанционке не приняли код на C++.

Почти переделал, но есть непонятный момент

Среда — Microsoft Visual C++ 6.0

class Car{
	private:
		char* marka; //марка авто
		int power; //мощность двигателя в кВт
		float cost; //стоимость в тыс. $
		int displacement; //объём двигателя
	public:
		void setData(char* m, int pw, float p, int dis) {
		  marka = m;
		  power = pw;
		  cost = p;
		  displacement = dis;
		}
		std::string getData() {
			string to_return = "Marka is ";
			to_return += marka;
		    return to_return;
		}
	public:
		Car(char* m = "Renault", int pw = def_power, float p = def_price, int dis = def_displacement){ //создание объекта по умолчанию
			marka = m;
			power = pw;
			cost = p;
			displacement = dis;
		};
	public:
		void Print(){ //вывод параметров на экран
			cout << getData() << endl;
			cout << "Price equals " << cost << " thousand $" << endl;
			cout << "Power equals " << power << " kW" << endl;
			cout << "Displacement equals " << displacement << " cm3" << endl;
		};
		void Input(); //функция ввода параметров, ещё не определена
		};
 
void Car::Input(){ //функция ввода параметров
        char *marka_ = new char; //создаём динамический объект marka
        std::cout << "Input mark: "; //введите марку авто
        std::cin >> marka_;
        std::cout << std::endl;
 
		do{
        std::cout << "Input power (kW): "; //введите мощность авто в кВт
        std::cin >> power;
		} while(power < 0);
        std::cout << std::endl;
 
		do{
        std::cout << "Input cost (thousand $): "; //введите стоимости авто в тыс. $
        std::cin >> cost;
		} while(cost < 0);
        std::cout << std::endl;

		do{
		std::cout << "Input displacement (cm3): "; //введите объём двигателя в см3
        std::cin >> displacement;
		} while(displacement < 0);
        std::cout << std::endl;
 
        Car ipnut; //создание нового объекта
		ipnut.setData(marka_,power,cost,displacement);
		ipnut.Print(); //вывод параметров объекта на экран
		delete marka_;
    };

Строчка delete marka_ вызывает ошибку

DAMAGE: after Normal block (#80) at 0x008C1990

Всё это при том, что в основном cpp файле удаление динамических объектов работает.

Кроме того, хотелось бы на всякий случай сделать проверку, введено ли число.

А ещё написали «Разделяйте код заголовочных файлов .h, реализацию методов сделайте в соответствующих cpp-файлах».

UPD: главную проблему решил, изменив просто char на char[16]

От:

maxidroms

Россия

 
Дата:  05.04.05 12:32
Оценка:

Вот представлен следущий код:

ENUM_SERVICE_STATUS *status;
DWORD szReturned;
MyFunction(status,szReturned);
for (int i=0;i<(int)szReturned;i++)
{
cout << status[i].lpDisplayName << endl;
}
delete status;

MyFunction выглядит след. образом.

void MyFunction(ENUM_SERVICE_STATUS *&status,&szReturned)
{
status=new ENUM_SERVICE_STATUS[100];
szReturned=100;
}

Функция отрабатывает нормально. в цикле после функции я получаю всю необходимую инфу.

но почему у меня вылетает программа на delete. если его нет тот все ОК. Но тогда ведь паметь не освобождается.
Что я неправильно сделал?

От: Аноним

 
Дата:  05.04.05 12:33
Оценка:

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

delete []

От:

korzhik

Россия

 
Дата:  05.04.05 12:33
Оценка:

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

M>Вот представлен следущий код:

  delete [] status;

От:

maxidroms

Россия

 
Дата:  05.04.05 12:37
Оценка:

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

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


M>>Вот представлен следущий код:


K>

K>  delete [] status;
K>

delete [] status;

та же ошибка!

пишет как и раньше
File dbgheap.c
line 1132

expression _CrtIsValidHeapPointer(pUserData)

Вылетает на ASSERT в этом файле.

От:

Bell

Россия

 
Дата:  05.04.05 12:39
Оценка:

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

Если для выделения используешь new[], то освобождай с помощью delete []. Иначе — неопределенное поведение.

Любите книгу — источник знаний (с) М.Горький

От:

maxidroms

Россия

 
Дата:  05.04.05 12:40
Оценка:

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

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


B>Если для выделения используешь new[], то освобождай с помощью delete []. Иначе — неопределенное поведение.

Понимаю но….

delete [] status;

та же ошибка!

пишет как и раньше
File dbgheap.c
line 1132

expression _CrtIsValidHeapPointer(pUserData)

Вылетает на ASSERT в этом файле.

От:

korzhik

Россия

 
Дата:  05.04.05 12:42
Оценка:

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

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


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


M>>>Вот представлен следущий код:


K>>

K>>  delete [] status;
K>>



M>delete [] status;


M>та же ошибка!


M>пишет как и раньше

M>File dbgheap.c
M>line 1132

M>expression _CrtIsValidHeapPointer(pUserData)


M>Вылетает на ASSERT в этом файле.

у тебя одна программа или используешь dll?

От:

maxidroms

Россия

 
Дата:  05.04.05 12:43
Оценка:

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

K>у тебя одна программа или используешь dll?

Использую COM.

Память выделяется в COM — объекте.

От:

SergeyL

Россия

 
Дата:  05.04.05 12:54
Оценка:

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

M>Использую COM.



M>Память выделяется в COM — объекте.

void MyFunction(ENUM_SERVICE_STATUS *&status,&szReturned)

Так эта функция — метод COM интерфейса ?

От:

nabor

Россия

 
Дата:  05.04.05 12:55
Оценка:

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

B>Если для выделения используешь new[], то освобождай с помощью delete []. Иначе — неопределенное поведение.

Не совсем так. new[] выделяет массив, а delete [] вызывает для каждого из удаляемых объектов деструктор.

Убиваю принцесс, спасаю драконов…

От:

maxidroms

Россия

 
Дата:  05.04.05 12:58
Оценка:

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

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

M>>Использую COM.



M>>Память выделяется в COM — объекте.

SL>

SL>void MyFunction(ENUM_SERVICE_STATUS *&status,&szReturned)
SL>



SL>Так эта функция — метод COM интерфейса ?

Совершенно верно. Я просто сокращенно написал для читабельности на форуме.

на самом деле все выглядит так:

cout << «Starting service » << «messenger» << endl;
ENUM_SERVICE_STATUS *status;
DWORD szReturned;
pManageService->IWantEnumService(«maxidrom»,status,szReturned);
for (int i=0;i<(int)szReturned;i++)
{
cout << status[i].lpDisplayName << endl;
}
delete [] status;
cout << «Releasing instance» << endl;
pManageService->Release();

cout << «Shuting down COM» << endl;
CoUninitialize();

Простите если это сокращение уменьшило объективность.
Я считал это не важной деталью.(Знать где упасть можно было бы сена подстелить)
Так это что то меняет? Можете что то посоветовать чтобы освобождать память без ошибок?

От:

SergeyL

Россия

 
Дата:  05.04.05 13:07
Оценка:

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

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


M>на самом деле все выглядит так:


M> cout << «Starting service » << «messenger» << endl;

M> ENUM_SERVICE_STATUS *status;
M> DWORD szReturned;
M> pManageService->IWantEnumService(«maxidrom»,status,szReturned);
M> for (int i=0;i<(int)szReturned;i++)
M> {
M> cout << status[i].lpDisplayName << endl;
M> }
M> delete [] status;
M> cout << «Releasing instance» << endl;
M> pManageService->Release();

M> cout << «Shuting down COM» << endl;

M> CoUninitialize();

M>Простите если это сокращение уменьшило объективность.


M>Я считал это не важной деталью.(Знать где упасть можно было бы сена подстелить)
M>Так это что то меняет? Можете что то посоветовать чтобы освобождать память без ошибок?

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

От:

korzhik

Россия

 
Дата:  05.04.05 13:13
Оценка:

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

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

K>>у тебя одна программа или используешь dll?



M>Использую COM.

M>Память выделяется в COM — объекте.

скорей всего проблема в том что вы используете статическую линковку с CRT. в итоге у вас получается две кучи. В одной куче вы выделяете память, а вдругой освобождаете, поэтому и происходит ошибка. Используйте динамическую линковку с CRT (/MDd, /MD) или используйте к примеру CoTaskMemAlloc,CoTaskMemFree

От:

maxidroms

Россия

 
Дата:  05.04.05 14:15
Оценка:

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

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


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

K>>>у тебя одна программа или используешь dll?



M>>Использую COM.

M>>Память выделяется в COM — объекте.

K>скорей всего проблема в том что вы используете статическую линковку с CRT. в итоге у вас получается две кучи. В одной куче вы выделяете память, а вдругой освобождаете, поэтому и происходит ошибка. Используйте динамическую линковку с CRT (/MDd, /MD) или используйте к примеру CoTaskMemAlloc,CoTaskMemFree

Чтож…отчасти вы правы оказались.

Действительно в свойствах проекта надо поставить /MD в любом случае.

При этом если запускать программу как CTRL-F5 она уже не вылетает при delete. Но если запустить как F5 то она вылетает в дебаг.

однако если чтроку delete status; перенести после COMObject->Release() или после CoUninitialize() то и вылетать перестает совсем.

От:

MaximE

Великобритания

 
Дата:  05.04.05 14:23
Оценка:

nabor wrote:

> B>Если для выделения используешь new[], то освобождай с помощью delete []. Иначе — неопределенное поведение.

> Не совсем так.

Что не совсем так? Стандарт гарантирует undefined behavior.

> new[] выделяет массив

… и затем вызывает дефолтный конструктор у не POD типов.

> , а delete [] вызывает для каждого из удаляемых объектов деструктор.

… и удаляет память.

(речь идет о ключевых словах, а не об одноименных операторах)


Maxim Yegorushkin

Posted via RSDN NNTP Server 1.9

От:

korzhik

Россия

 
Дата:  05.04.05 14:25
Оценка:

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

M>При этом если запускать программу как CTRL-F5 она уже не вылетает при delete. Но если запустить как F5 то она вылетает в дебаг.

Значит не всё ещё в порядке, хорошы бы конечно разобраться в чём дело. Сделать пошаговую отладку до места где вылетает.

M>однако если чтроку delete status; перенести после COMObject->Release() или после CoUninitialize() то и вылетать перестает совсем.

а CoTaskMemAlloc,CoTaskMemFree пробовали?

От:

maxidroms

Россия

 
Дата:  05.04.05 14:31
Оценка:

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

M>>При этом если запускать программу как CTRL-F5 она уже не вылетает при delete. Но если запустить как F5 то она вылетает в дебаг.


K>Значит не всё ещё в порядке, хорошы бы конечно разобраться в чём дело. Сделать пошаговую отладку до места где вылетает.

Пошаговая отладка идет до делете. Дальше вылет в файл osfinfo,c строка 477 в функцию
void __cdecl _unlock_fhandle (
int fh
)
{
LeaveCriticalSection( &(_pioinfo(fh)->lock) );
}

M>>однако если чтроку delete status; перенести после COMObject->Release() или после CoUninitialize() то и вылетать перестает совсем.



K>а CoTaskMemAlloc,CoTaskMemFree пробовали?

Вроде пробовал. Я так понимаю надо было заменить
status=new ENUM_SERVICE_STATUS[100];
на
status=(ENUM_SERVICE_STATUS*)CoTaskMemAlloc(sizeof(ENUM_SERVICE_STATUS)*100);
так?

Если да то он на этой строчке отваливается. Не может так выделить

От:

maxidroms

Россия

 
Дата:  05.04.05 14:34
Оценка:

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

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


M>>При этом если запускать программу как CTRL-F5 она уже не вылетает при delete. Но если запустить как F5 то она вылетает в дебаг.

K>Значит не всё ещё в порядке, хорошы бы конечно разобраться в чём дело. Сделать пошаговую отладку до места где вылетает.

M>>однако если чтроку delete status; перенести после COMObject->Release() или после CoUninitialize() то и вылетать перестает совсем.


K>а CoTaskMemAlloc,CoTaskMemFree пробовали?

Слушайте а вы вообще работаете или в инете сидите? У нас почти как переписка по чату!
Мало людей кто так оперативно отвечает и так занят этой проблемой. Как будто у вас дел своих нет.

За это огромное вам спасибо!!!!Побольше таких людей.

От:

Кодт

Россия

 
Дата:  05.04.05 14:45
Оценка:

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

M>Использую COM.


M>Память выделяется в COM — объекте.

НИКОГДА не возвращай из COM-методов память, выделенную С++ными средствами.
Только ::TaskMemAlloc() | IMalloc::Alloc()
Иначе огребёшь уйму приключений при первом же маршалинге.

http://files.rsdn.org/4783/catsmiley.gif Перекуём баги на фичи!

От:

maxidroms

Россия

 
Дата:  05.04.05 15:14
Оценка:

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

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


M>>При этом если запускать программу как CTRL-F5 она уже не вылетает при delete. Но если запустить как F5 то она вылетает в дебаг.

K>Значит не всё ещё в порядке, хорошы бы конечно разобраться в чём дело. Сделать пошаговую отладку до места где вылетает.

M>>однако если чтроку delete status; перенести после COMObject->Release() или после CoUninitialize() то и вылетать перестает совсем.


K>а CoTaskMemAlloc,CoTaskMemFree пробовали?

Все…огромное спасибо…дейтвительно делать надо все через CoTaskMemAlloc

просто я неправильно немного делал. Сейчас все работатет

От:

nabor

Россия

 
Дата:  05.04.05 15:42
Оценка:

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

>> Не совсем так.

ME>Что не совсем так? Стандарт гарантирует undefined behavior.
>> new[] выделяет массив
ME>… и затем вызывает дефолтный конструктор у не POD типов.
>> , а delete [] вызывает для каждого из удаляемых объектов деструктор.
ME>… и удаляет память.
ME>(речь идет о ключевых словах, а не об одноименных операторах)

Что ж, видимо я не неправильно понял Ваш первый пост. Хотя это уже флейм. Из сказанного Вами следует, что всегда надо после new [] освобождать память при помощи delete [].

Убиваю принцесс, спасаю драконов…

От:

MaximE

Великобритания

 
Дата:  05.04.05 15:47
Оценка:

nabor wrote:

> Из сказанного Вами следует, что всегда надо после new [] освобождать память при помощи delete [].

Это действительно так.


Maxim Yegorushkin

Posted via RSDN NNTP Server 1.9

От:

Bell

Россия

 
Дата:  05.04.05 15:51
Оценка:

+1

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

N>Что ж, видимо я не неправильно понял Ваш первый пост. Хотя это уже флейм. Из сказанного Вами следует, что всегда надо после new [] освобождать память при помощи delete [].

Пост был мой , и поняли Вы его правильно — после new [] освобождать память нужно при помощи delete [].
Тема эта обсуждалась не раз, и не два, так что все подробности можно легко найти в поиске.

Любите книгу — источник знаний (с) М.Горький

От:

korzhik

Россия

 
Дата:  05.04.05 16:11
Оценка:

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

M>Слушайте а вы вообще работаете или в инете сидите? У нас почти как переписка по чату!

Работаю конечно.

M>Мало людей кто так оперативно отвечает и так занят этой проблемой. Как будто у вас дел своих нет.

Дела есть. Просто работать без перерыва сложно.
Если есть возможность работаю примерно в режиме 20/5 (20 минут работаю 5 минут отдыхаю)
На вашу проблему я много времени не потратил.

M>За это огромное вам спасибо!!!!Побольше таких людей.

Тут таких много

Подождите ...

Wait...

  • Переместить
  • Удалить
  • Выделить ветку

Пока на собственное сообщение не было ответов, его можно удалить.

const char * c = str.c_str();
delete[] c; // Gives error.

c is a pointer to the contents of str that’s still owned and managed by the str object itself, may not be dynamically allocated (e.g. it could be a pointer to a Short String Optimisation buffer internal to the str object), let alone by new[], and even if it happens to be the str object will do a delete[] when it goes out of scope or has copied the data to a larger buffer for whatever reason. Summarily, after calling c_str() you can use the pointer until the str object is resized or «destructed», but don’t need to do any clean-up yourself.


Looking at the rest of your code…

int len = str.length();
const char * c = str.c_str();
unsigned short * s = new unsigned short[len];
for (int i = 0; i < len; i++) {
    s[i] = c[i] - '0'; // I dislike this cheat
}
delete[] c; // Gives error.

…the only error per se is that you delete[] c, but you don’t delete[] s and probably should somewhere, some time after it’s no longer needed.

That said, you can use std::vector to store the ASCII codes like this (for C++11):

std::vector<unsigned short> s;

for (char c : str)
    s.push_back(c - '0');

If you don’t have C++11, then:

for (int i = 0; i < str.length(); ++i)
    s.push_back(c[i] - '0');

…or if you want to try iterators

std::vector<unsigned short> s;
for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
    s.push_back(*i - '0');

You could also use std::copy with an inserter, more declarative but a bit over-the-top IMHO:

std::copy(str.begin(), str.end(), std::back_inserter(s));

  • Remove From My Forums
  • Question

  • Hey there!!!

    I am getting a runtime error when using the delete operator for deleting an array in my code.

    Please help me out…

    Below is my code:

    // mc.cpp :Write a program that "speaks" pig-latin. Words in pig-latin are taken from English. To form a word in pig-latin, the first letter of the english word beginning with a
    //consonant is removed and added at the end of the word,adding letters "ay" after the moved consonant. Words that begin with a vowel are simply appended with ay. Thus, in pig-latin,
    //pig-latin is igpay-atinlay. Your program will read a sentence at a time using fgets. It is to parse the words into strings. as words are parsed, they are to be converted to pig-latin
    //and printed.
    //Author Evolution; Date: 9 March 2013;
    													/*PLEASE DON'T USE ANY CHARACTERS EXCEPT ENGLISH ALPHABETS AND SPACES*/
    #include<iostream>
    using namespace std;
    class piglatin
    {
    private:
    	char *sen;
    public:
    	piglatin(void);
    	char * get_sen();
    	void parse(char *);
    	void convrt(char *);
    	~piglatin(void);
    };
    piglatin::piglatin(void)
    {
    		sen=new char[1000];
    }
    char * piglatin::get_sen()
    {
    	cout<<"Enter a sentence:"<<endl;
    	fgets(sen,1000,stdin);
    	cout<<endl;
    	return sen;
    }
    void piglatin::parse(char *s)
    {
    	char *word,*w;
    	while(*s!=0)
    	{
    		word=new char[15];
    		w=word;
    		while(*s!=32)
    		{
    			if(*s=='n'||*s==0)
    				break;
    			*word=*s;
    			word++;
    			s++;
    		}
    		*word=0;
    		convrt(w);
    		s++;
    		delete []word;//THIS LINE GIVES ME THE ERROR
    	}
    }
    void piglatin::convrt(char *c)
    {
    	int len,i;
    	len=strlen(c);
    	for(i=0;i<len;i++)
    	{
    		if(c[i]!=32)
    			break;
    	}
    	if(i==len)
    	{
    		c[len]=0;
    		cout<<c<<" ";
    		return;
    	}
    	if(*c!='a'&&*c!='A'&&*c!='e'&&*c!='E'&&*c!='i'&&*c!='I'&&*c!='o'&&*c!='O'&&*c!='u'&&*c!='U')
    	{
    		c[len]=*c;
    		c[len+1]='a';
    		c[len+2]='y';
    		c[len+3]=0;
    		c++;
    		cout<<c<<" ";
    	}
    	else
    	{
    		c[len]='a';
    		c[len+1]='y';
    		c[len+2]=0;
    		cout<<c<<" ";
    	}
    }
    piglatin::~piglatin(void)
    {
    		delete []sen;
    }
    int main()
    {
    	cout<<"Hey there!!!... I am a machine I converts English into PIG-LATIN...:)..."<<endl<<endl;
    	piglatin mc;
    	mc.parse(mc.get_sen());
    	cout<<endl;
    	return 0;
    }

    And the surprising part is that when using the same code with TURBO C++ compiler there is no error at all and it is perfectly working.

    But in visual c++ its giving that run time error. Of course, hiding that delete statement gives the proper output and the program runs perfectly just as in the case of TURBO C++ compiler…but still as a coder i must know that why is
    this happening…

    Hope u understand…

    So please help me out…

    Your little help could help me gaining a lot…

    Thanks a million…:)

Answers

  • On 3/18/2013 1:34 PM, viiiiiicky wrote:

        arr=new int[size];

    You allocate a block of memory, let’s call it A. arr points to A.

            temparr=new int[size+newsize];

    You allocate another block of memory, let’s call it B. temparr points to B

            arr=temparr;

    Now both arr and temparr point to B. You no longer have any means to access A. A is leaked.

            //delete []temparr;//THIS IS THE ERROR GENERATOR!!!
        delete []arr;

    Recall that both arr and temparr point to the same block, B. If you use delete[] on both of them, you are deallocating the same block of memory twice. The first time is OK, the second time is illegal.


    Igor Tandetnik

    • Marked as answer by

      Thursday, March 21, 2013 3:10 PM

  • When you do word++  you modify the pointer that was returned by new. You can only delete the exact same pointer value that you received from new.

    • Marked as answer by
      viiiiiicky
      Sunday, March 17, 2013 7:29 AM

Повреждение кучи обнаружено после нормального блока # 151, когда я пытаюсь использовать delete[] в моем коде

#include "Queue.h"
void main() {
queue* stk = new queue;
initQueue(stk, 4);
enqueue(stk, 9);
enqueue(stk, 4);
enqueue(stk, 3);
enqueue(stk, 7);

while (!isEmpty(stk)) {
std::cout << "Popping number:" << dequeue(stk) << std::endl;
}

cleanQueue(stk);
delete stk;

system("Pause");
}

Это функция удаления:

void cleanQueue(queue* q) {
delete[] q->_elements;
}

это структура:

typedef struct queue
{
int * _elements;
int _maxSize;
int _count;
} queue;

Может кто-нибудь сказать, пожалуйста, почему это происходит и что я должен сделать, чтобы это исправить?
Благодарю.

        #include "Queue.h"void enqueue(queue* q, unsigned int newValue) {
int i = 0;
if (!isFull(q)) {
q->_count++;
q->_elements[0] = newValue;
for (i = q->_count; i > 0; i--) {
q->_elements[i] = q->_elements[i - 1];
}
}
}

int dequeue(queue* q) {
int ans = -1;

if (!isEmpty(q)) {
ans = q->_elements[q->_count];
q->_count--;

}
return(ans);
}

void initQueue(queue* q, unsigned int size) {
q->_count = 0;
q->_maxSize = size;
q->_elements = new int[size];
}

void cleanQueue(queue* q) {
delete[] q->_elements;
}

bool isFull(queue* q) {
return(q->_count == q->_maxSize);
}

bool isEmpty(queue* q) {
return(q->_count == 0);
}

0

Решение

Представьте, что в вашей очереди есть один элемент, и ваш maxSize также равен 1.
Он не пустой, поэтому вы продолжаете читать значение в _count в элементах.
Поэтому он читает элементы [1] (поскольку _count равен 1), когда единственный элемент находится в элементах [0]. Если это проходит после окончания вашего выделения, у вас будет ошибка памяти (неопределенное поведение), но вы всегда будете читать неправильное значение.

int dequeue(queue* q) {
int ans = -1;

if (!isEmpty(q)) {
ans = q->_elements[q->_count];
q->_count--;

}
return(ans);
}

Вы, вероятно, хотите вычесть один из _count.

Ваша очередь также имеет логическую ошибку, так как вы перемещаете свои элементы после Вы пишете новое значение, поэтому вы что-то переписали.

void enqueue(queue* q, unsigned int newValue) {
int i = 0;
if (!isFull(q)) {
q->_count++;
q->_elements[0] = newValue; // <<<<<<<< Here.
for (i = q->_count; i > 0; i--) {
q->_elements[i] = q->_elements[i - 1];
}
}
}

0

Другие решения

В вашей функции enqueue значение count достигает 4. Затем вы пытаетесь обратиться к нему в цикле for как q-> elements [4], в то время как самый высокий индекс в вашем массиве равен 3.

0

Как сказал Алекс, ваш enqueue() функция имеет ошибку. Попробуйте следующий код.

void enqueue(queue* q, unsigned int newValue) {
int i = 0;
if (!isFull(q)) {
for (i = q->_count; i > 0; i--) {
q->_elements[i] = q->_elements[i - 1];
}
q->_elements[0] = newValue;
q->_count++;
}
}

0

Понравилась статья? Поделить с друзьями:
  • Demon souls ошибка 009
  • Democracy 4 ошибка 0xc000007b
  • Demagog ошибка голосового движка
  • Deluxe посудомоечная машина коды ошибок
  • Delta ошибка связи силовой платы