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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 16.05.2013, 10:59   #1
Homa_1983
Пользователь
 
Регистрация: 14.10.2011
Сообщений: 29
По умолчанию

Всем доброго времени суток. Помогите, пожалуйста - сам не могу понять где конкретно ошибка. Это моя первая программка на C++ Builder. Перевожу ее из Visual Studio 2006.

Проблема в следующем. Все компилируется и работает нормально, но если выполнять обработчики в следующей последовательности (NameLabeledEditChange, PayLabeledEditChang, AddButtonClick, EraseButtonClick, ExitButtonClick), то возникает ошибка по завершении: Debugger exception notification 'Invalid pointer operation'

Юнит приведен ниже:

Последний раз редактировалось Stilet; 17.05.2013 в 08:08.
Homa_1983 вне форума Ответить с цитированием
Старый 16.05.2013, 11:05   #2
Homa_1983
Пользователь
 
Регистрация: 14.10.2011
Сообщений: 29
По умолчанию

Код:
#include <vcl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#pragma hdrstop

#include "UBabki_2.h"
//-------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMyMainForm *MyMainForm;
AnsiString EditTextName;
AnsiString EditTextPay;
struct CalcData* pNT;
struct CalcData* pNTnew;
char* Mem_input_data;
char* pBuf;
int LenName = 0;
int LenPay = 0;
int LenNamePay = 0;
int SumLenNamePay = 0;
int RecNum = 0;
int RecNumOld = 0;
int i = 0;
int Lenght = 0;
double sum = 0;
//-------------------------------------------------------------------------
__fastcall TMyMainForm::TMyMainForm(TComponent* Owner)
	: TForm(Owner)
{
}
//-------------------------------------------------------------------------
void __fastcall TMyMainForm::ExitButtonClick(TObject *Sender)
{
	Application->Terminate();
}
//-------------------------------------------------------------------------
void __fastcall TMyMainForm::NameLabeledEditChange(TObject *Sender)
{
	EditTextName = AnsiString(NameLabeledEdit->Text);
	LenName = StrLen(EditTextName.c_str());
}
//-------------------------------------------------------------------------
void __fastcall TMyMainForm::PayLabeledEditChange(TObject *Sender)
{
	EditTextPay = AnsiString(PayLabeledEdit->Text);
	LenPay = StrLen(EditTextPay.c_str());
}
//-------------------------------------------------------------------------

void __fastcall TMyMainForm::AddButtonClick(TObject *Sender)
{

	if( LenName == 0 && LenPay == 0 )
	{
		ProgramMessageEdit->Text = "Bla-Bla-Bla";
	}

	if( LenName != 0 && LenPay == 0 )
	{
		ProgramMessageEdit->Text = "Bla-Bla-Bla";
	}

	if( LenName == 0 && LenPay != 0 )
	{
		ProgramMessageEdit->Text = "Bla-Bla-Bla";
	}

	if( LenName != 0 && LenPay != 0 )
	{
		LenNamePay = LenName + LenPay;
		SumLenNamePay += LenName + LenPay;

		if( RecNum == 0 )
		{
			RecNum = 1;

			pNT = (CalcData *) malloc( RecNum * sizeof( struct CalcData ) );
			if ( pNT == 0 )
			{
				AnsiString msg = "Memory allocation error!";
				ShowMessage(msg);
				Application->Terminate();
			}
			memset( pNT, 0, RecNum * sizeof( struct CalcData ) );
		}
		else
		{
			RecNumOld = RecNum;
			RecNum = RecNum + 1;
			pNTnew = (CalcData *) malloc( RecNum * sizeof( struct CalcData ) );
			if ( pNTnew == 0 )
			{
				AnsiString msg = "Memory allocation error!";
				ShowMessage(msg);
				Application->Terminate();
			}
			memset( pNTnew, 0, RecNum * sizeof( struct CalcData ) );
			memcpy( pNTnew, pNT, RecNumOld * sizeof( struct CalcData ) );
			free (pNT);
			pNT = pNTnew;
		}

		strcpy( ( pNT + RecNum - 1 ) -> name, EditTextName.c_str() );
		(pNT+RecNum-1)->pay = atof( EditTextPay.c_str() );

		PayLabeledEdit->Text = "";
		NameLabeledEdit->Text = "";
		ProgramMessageEdit->Text = "";

		if( RecNum != 0 )
		{

			Mem_input_data = (char *) malloc( LenNamePay +  9 );
			if ( Mem_input_data == 0 )
			{
				AnsiString msg = "Memory allocation error!";
				ShowMessage(msg);
				Application->Terminate();
			}

			sprintf(Mem_input_data,"%s: %lg (Bla.)",(pNT+RecNum-1)->name,(pNT+RecNum-1)->pay);

			InputDataMemo->Lines->Add(AnsiString(Mem_input_data));

			free (Mem_input_data);
		}

	}
}
//-------------------------------------------------------------------------

void __fastcall TMyMainForm::CalcButtonClick(TObject *Sender)
{

	if( RecNum != 0 )
	{
		sum = calc(RecNum, pNT);

		pBuf = (char *) malloc( 19*RecNum + SumLenNamePay + 166 + SumLenNamePay );
		if ( pBuf == 0 )
		{
			AnsiString msg = "Memory allocation error!";
			ShowMessage(msg);
			Application->Terminate();
		}

		output_data(RecNum, sum, pNT, pBuf);

//		AnsiString MsgFinal = pBuf;
//		ShowMessage(MsgFinal);

		MessageBox(NULL, pBuf, "final", MB_OK);

		free (pBuf);
	}
	else
	{
		ProgramMessageEdit->Text = "Bla-Bla-Bla";
	}
}
//-------------------------------------------------------------------------

void __fastcall TMyMainForm::EraseButtonClick(TObject *Sender)
{
	int i;

	if( RecNum != 0 )
	{
		if( pNT != 0 )
		{
			memset( pNT, 0, RecNum * sizeof( struct CalcData ) );
			free( pNT );
		}

//		InputDataMemo->Lines->Clear();
		for( i = 0; i < RecNum; i++ )
		{
			InputDataMemo->Lines->Delete(i);
		}

		LenNamePay = 0;
		SumLenNamePay = 0;
		RecNum = 0;
	}

        LenNamePay = LenName + LenPay;
	if (LenPay != 0 ) PayLabeledEdit->Text = "";
	if (LenName != 0 ) NameLabeledEdit->Text = "";
	ProgramMessageEdit->Text = "";
}
Homa_1983 вне форума Ответить с цитированием
Старый 16.05.2013, 11:06   #3
Homa_1983
Пользователь
 
Регистрация: 14.10.2011
Сообщений: 29
По умолчанию

Ошибку порождает попытка очистить Мемо:
Код:
InputDataMemo->Lines->Clear();
или
Код:
for( i = 0; i < RecNum; i++ )
{
	InputDataMemo->Lines->Delete(i);
}
без разницы.
Дело, скорее всего, в выделении и последующем освобождении памяти. Не могу понять где ошибся.

Заранее спасибо всем откликнувшимся )))
Homa_1983 вне форума Ответить с цитированием
Старый 16.05.2013, 13:50   #4
FataLL
Форумчанин
 
Аватар для FataLL
 
Регистрация: 29.01.2013
Сообщений: 319
По умолчанию

Как описаны структуры?

Для Mem_input_data надо выделять памяти на один байт больше, для '\0'. К тому же, то, что ты ввёл в едите в качестве Pay, совершенно не равняется длине вещественного числа, которое ты пытаешься в эту строку запихать. Т.е., ты ввёл 3.5, а пытаешься записать 0.3500000000Е+01. В результате - переполнение буфера со всеми вытекающими...

И вообще, зачем такие трудности с выделением памяти?
Код:
AnsiString sData;
sData.sprintf("%s: %lg (Bla.)",(pNT+RecNum-1)->name,(pNT+RecNum-1)->pay);

InputDataMemo->Lines->Add( sData );
И я уже умолчу про динамический массив...

Последний раз редактировалось Stilet; 17.05.2013 в 08:10.
FataLL вне форума Ответить с цитированием
Старый 16.05.2013, 16:41   #5
Homa_1983
Пользователь
 
Регистрация: 14.10.2011
Сообщений: 29
По умолчанию

Структура и функции объявлены в MyFunctions.h. Почему-то в выложенном мной коде потерялся соответствующий include (

Код:
#ifndef MyFunctionsH
#define MyFunctionsH
//---------------------------------------------------------------------------
struct CalcData
{
	char name[128];
	double pay;
	double dolg;
};

double calc(int N, struct CalcData* var);

void output_data(int n, double sum, struct CalcData* var, char* pointer);
//---------------------------------------------------------------------------
#endif
Такое выделение памяти - это мое наследство от поверхностного знания С . Другие способы еще предстоит узнать. Спасибо за критику.
Я, вообще, только знакомлюсь с понятием классов со всеми вытекающими...

А что не так с динамическими массивами?

Спасибо, буду копать дальше...

Последний раз редактировалось Stilet; 17.05.2013 в 08:13.
Homa_1983 вне форума Ответить с цитированием
Старый 16.05.2013, 17:26   #6
FataLL
Форумчанин
 
Аватар для FataLL
 
Регистрация: 29.01.2013
Сообщений: 319
По умолчанию

Цитата:
Сообщение от Homa_1983 Посмотреть сообщение
А что не так с динамическими массивами?
Память можно выделить немедленно, если её много не надо. Например, сотворить массив структур и не парится с выделениями памяти.
Код:
struct CalcData MyData[1000];

MyData[0].name = ...;
MyData[0].pay = ...;
Можно использовать динамический массив, что ты по сути и делаешь, но очень забавно.
Код:
struct CalcData **MyData;

MyData = (struct CalcData **) new (struct CalcData *) [1000];

for( int i = 0; i < 1000; i++ )
{
  MyData[i] = new (struct CalcData);
}

MyData[0]->name = ...;
MyData[0]->pay = ...;
Можно использовать список VCL или разнообразные контейнеры STL
Код:
TList* MyData = new TList;

struct CalcData* Item = new (struct CalcData);
Item->name = ...;
Item->Pay = ...;

MyData->Add( Item );

или

std::vector<struct CalcData *> MyData;

struct CalcData* Item = new (struct CalcData);
Item->name = ...;
Item->Pay = ...;

MyData.push_back( Item );
Короче, масса, масса готовых вариантов, чтоб не париться с разработкой велосипеда...

Последний раз редактировалось FataLL; 17.05.2013 в 09:27. Причина: Звёздочку забыл, балда...
FataLL вне форума Ответить с цитированием
Старый 16.05.2013, 22:31   #7
Homa_1983
Пользователь
 
Регистрация: 14.10.2011
Сообщений: 29
По умолчанию

Спасибо
Homa_1983 вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
При выполнение кода выводится Debugger exception notification sasha198407 БД в Delphi 0 31.03.2012 11:50
Ошибка Debugger Exception Notification VKorablev C++ Builder 5 24.11.2011 16:58
Invalid Pointer Operation Стелс Компоненты Delphi 1 25.09.2011 21:24
Ошибка - Debugger exception notification Football_lady БД в Delphi 1 15.01.2010 19:07
Invalid Pointer Operation Unconnected Общие вопросы Delphi 3 21.02.2009 20:23