-
June 9th, 2009, 08:26 PM
#1
Access Violation Error Help
I keep getting this message that I cant figure out how to fix.
Here is the error:
First-chance exception at 0x6380f8bc (msvcr90d.dll) in Final.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
Unhandled exception at 0x6380f8bc (msvcr90d.dll) in Final.exe: 0xC0000005: Access violation reading location 0xcdcdcdcd.
And the symbols are not loading for: kernel32.dll and ntdll.dll.
What did I do wrong? ( I know that it has something to do with strlen and the buffer in the GetPet function.)
(if my code looks funny it is bucause it is an assignment for college. SOme of the things I have done here are a requirment; sorry. And I know that it has some C in it. This is something that I have been informed by my instructor as part of the learning process; vectors, structs, blah, blah, will come later next term.)
Here is my code:
Code:
#define _CRTDBG_MAP_ALLOC
#include < iostream >
#include < iomanip >
#include < cctype >
#include < cstring >
using std::cout;
using std::cin;
using std::endl;
using std::setw;
using namespace std;
//Variables
const int MAX = 60;
const int CAT = 20;
const int DOG = 35;
int menu_choice;
char again = 'Y';
char ** petName = new char * [12];
char ** ownName = new char * [12];
char ** petType = new char * [12];
int animalcount = 0;
int catCount = 0;
int dogCount = 0;
int totalCount = 0;
int count[60] = {0};
int * arrayCount = &count[0];
int catCost = 0;
int dogCost = 0;
int overallCost = 0;
int input = 0;
//Functions
void MenuChoice( int &menu_choice );
void ProcessMenu( int &menu_choice );
void GetPet( char **& petName, char **& ownName, char **& petType );
void DisplayAll();
void RemovePet( char **& petName, char **& ownName, char **& petType );
void TotalCat( int &catCount, int &catCost );
void TotalDog( int &dogCount, int &dogCost );
void TotalDay( int &overallCost, int &catCost, int &dogCost, int &totalCount );
void AvgCap( int * &arrayCount );
char Exit( char again );
int main()
{
//Test for Leaks.
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
//Function Pointers
void (*fn_ptr_Menu)( int & );
fn_ptr_Menu = MenuChoice;
void (*fn_ptr_Process)( int & );
fn_ptr_Process = ProcessMenu;
while( again == 'Y' )
{
fn_ptr_Menu( menu_choice );
fn_ptr_Process( menu_choice );
}
//Delete Memory.
for( int i = 0; i < 12; i++)
{
delete[] petName[i];
delete[] ownName[i];
delete[] petType[i];
}
delete[] petName;
delete[] ownName;
delete[] petType;
system( "pause" );
return 0;
}
/***********************************************************************************************************************
*Name: MenuChoice
*Parameters: &menu_choice
*Return: none
*Purpose: This function is to display the menu to the user.
***********************************************************************************************************************/
void MenuChoice( int &menu_choice )
{
cout << "\t\t\t\n\nMenu\n\n" << endl;
cout << "1) Board a Critter " << endl;
cout << "2) Remove a Critter " << endl;
cout << "3) Display all Critters " << endl;
cout << "4) Count all Critters and Calculate Daily Proceeds " << endl;
cout << "5) Exit " << endl;
cout << "\n\nPlease enter a menu choice, 1 to 5: " ;
cin >> menu_choice;
}
/***********************************************************************************************************************
*Name: ProcessMenu
*Parameters: &menu_choice
*Return: none
*Purpose: This function is to process the menu choice.
***********************************************************************************************************************/
void ProcessMenu( int &menu_choice )
{
//Function Pointer
void (*fn_ptr_disAll)();
fn_ptr_disAll = DisplayAll;
if( menu_choice < 1 || menu_choice > 5 )
{
cout << "\n\nPlease enter a number between 1 and 5! " << endl;
}
else
{
switch ( menu_choice)
{
case 1 ://Get Pet.
{
fn_ptr_disAll();
GetPet( petName, ownName, petType );
break;
}
case 2://Remove Pet
{
fn_ptr_disAll();
RemovePet( petName, ownName, petType );
break;
}
case 3://Display all info
{
fn_ptr_disAll();
break;
}
case 4://Display totals and avg
{
fn_ptr_disAll();
TotalCat( catCount, catCost );
TotalDog( dogCount, dogCost );
TotalDay( overallCost, catCost, dogCost, totalCount) ;
AvgCap(arrayCount);
break;
}
case 5://Exit the program
{
again = Exit( again );
break;
}
}
}
}
/***********************************************************************************************************************
*Name: GetPet
*Parameters: petName, ownName, petType
*Return: none
*Purpose: This function gets the pet info from the user and gets the counts.
***********************************************************************************************************************/
void GetPet( char **& petName, char **& ownName, char **& petType )
{
char buffer[256] = {0};
if( animalcount == 12)
{
cout << "\n\nYou cannot board anymore animals! You are at maximum capacity! " << endl;
}
else
{
cout << "Which cage number do you want to add the critter to? ( 1 to 12) ";
cin >> input;
if( input < 1 || input > 12 )
{
cout << "Please input a number between 1 and 12! " << endl;
}
else
{
int k = input - 1;
char * str = 0;
//Get input for the Pet Name, Owner name, and Pet Type.
cout << "\n\nPlease input Pet Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, MAX );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
str = new char[strlen( buffer ) + 1];
strcpy( str, buffer );
petName[k] = str;
cout << "\n\nPlease input Owner Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer , MAX );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
str = new char[strlen( buffer ) + 1];
strcpy( str, buffer );
ownName[k] = str;
cout << "\n\nPlease input critter type: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, MAX );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
str = new char[strlen( buffer ) + 1];
strcpy( str, buffer );
petType[k] = str;
//Add to the counts.
animalcount++;
totalCount ++;
//Add count to the avg array function helper.
* arrayCount = totalCount;
arrayCount++;
//cat count.
int result;
_strlwr( *petType );
result = strcmp( *petType, "cat" );
if( result == 0 )
{
catCount++;
}
//dog count.
int result1;
_strlwr( *petType );
result1 = strcmp( *petType, "dog" );
if( result1 == 0 )
{
dogCount++;
}
cout << "\n\nCritter " << input << ", has been added! " << endl;
}
}
}
/***********************************************************************************************************************
*Name: DisplayAll
*Parameters: none
*Return: none
*Purpose: This function displays all pet infomation to the user.
***********************************************************************************************************************/
void DisplayAll()
{
cout.setf( ios::left );
cout << setw(10) << "Cage Num." << setw(20) << "Pet Name" << setw(20) << "Owner's Name" << setw(20) << "Pet Type" << endl;
for( int i = 0; i < 12; i++ )
{
cout << setw(10) << i+1 << setw(20) << petName[i] << setw(20) << ownName[i] << setw(20) << petType[i] << endl;
}
}
/***********************************************************************************************************************
*Name: RemovePet
*Parameters: petName, ownName, petType
*Return: none
*Purpose: This function displays all pet infomation to the user.
***********************************************************************************************************************/
void RemovePet( char **& petName, char **& ownName, char **& petType )
{
cout << "Which cage number do you want to remove the critter from? ( 1 to 12) ";
cin >> input;
int j = input - 1;
//Delete memory
delete [] petName[j];
delete [] ownName[j];
delete [] petType[j];
//Correct the count
animalcount--;
cout << "\n\nCritter " << input << ", has been removed. " << endl;
}
/***********************************************************************************************************************
*Name: Exit
*Parameters: again
*Return: none
*Purpose: This function exits the program.
***********************************************************************************************************************/
char Exit( char again )
{
again = 'n';
return again;
}
/***********************************************************************************************************************
*Name: TotalCat
*Parameters: int &catCount, int &catCost
*Return: none
*Purpose: This function finds the cat costs and displays.
***********************************************************************************************************************/
void TotalCat( int &catCount, int &catCost )
{
catCost = catCount * CAT;
cout << "\n\nThe Amount of Cats today is: " << catCount << ". " << endl;
cout << "The Sum of today's Cat earnings is: " << catCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: TotalDog
*Parameters: petType
*Return: none
*Purpose: This function finds the dog costs and displays.
***********************************************************************************************************************/
void TotalDog( int &dogCount, int &dogCost )
{
dogCost = dogCount * DOG;
cout << "\n\nThe Amount of Dogs today is: " << dogCount << ". " << endl;
cout << "The Sum of today's Dog earnings is: " << dogCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: TotalDay
*Parameters: int &overallCost, int &catCost, int &dogCost, int &animalcount
*Return: none
*Purpose: This function finds the total for the day.
***********************************************************************************************************************/
void TotalDay( int &overallCost, int &catCost, int &dogCost, int &totalCount )
{
overallCost = catCost + dogCost;
cout << "\n\nThe Total Amount of Critters today is: " << totalCount << ". " << endl;
cout << "Total amount of animals right now: " << animalcount << ". " << endl;
cout << "The Sum of today's earnings is: " << overallCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: AvgCap
*Parameters: none
*Return: none
*Purpose: This function finds the total avg for the day of animals.
***********************************************************************************************************************/
void AvgCap( int * &arrayCount )
{
int avg = 0;
int sum = 0;
arrayCount = &count[0];
for( int i = 0; i < totalCount; i++, arrayCount++ )
{
sum += * arrayCount;
}
avg = sum / totalCount;
cout << "\n\nThe Average Amount of Critters today is: " << avg << ". " << endl;
}
Last edited by Shadow_Govt; June 10th, 2009 at 10:43 PM.
-
June 9th, 2009, 10:34 PM
#2
Re: Access Violation Error Help
This might be of some help to understand those debug markers: http://www.nobugs.org/developer/win3..._crt_heap.html
Other then that, it also might be esier if you do use C++, things like std::string, std::vector, etc. This is a good site.
Last edited by STLDude; June 9th, 2009 at 10:37 PM.
Reason: Added links
-
June 10th, 2009, 12:35 AM
#3
Re: Access Violation Error Help
Alright. been messing with it a little bit and got most of it to work. I am leaking memory somewhere; cant figure it out. Something about a normal block line 155? Whenever I try to exit the program I get a heap assertion error.
Here is my new code:
Code:
#define _CRTDBG_MAP_ALLOC
#include < iostream >
#include < iomanip >
#include < cctype >
#include < cstring >
using std::cout;
using std::cin;
using std::endl;
using std::setw;
using namespace std;
//Variables
const int MAX = 60;
const int CAT = 20;
const int DOG = 35;
int menu_choice;
char again = 'Y';
char ** petName = new char * [256];
char ** petTemp = 0;
char ** ownName = new char * [256];
char ** ownTemp = 0;
char ** petType = new char * [256];
char ** typeTemp = 0;
int animalcount = 0;
int catCount = 0;
int dogCount = 0;
int totalCount = 0;
int count[60] = {0};
int * arrayCount = &count[0];
int catCost = 0;
int dogCost = 0;
int overallCost = 0;
int input = 0;
//Functions
void MenuChoice( int &menu_choice );
void ProcessMenu( int &menu_choice );
void GetPet( char **& petName, char **& ownName, char **& petType );
void DisplayAll();
void RemovePet( char **& petName, char **& ownName, char **& petType );
void TotalCat( int &catCount, int &catCost );
void TotalDog( int &dogCount, int &dogCost );
void TotalDay( int &overallCost, int &catCost, int &dogCost, int &totalCount );
void AvgCap( int * &arrayCount );
char Exit( char again );
int main()
{
//Test for Leaks.
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
//Function Pointers
void (*fn_ptr_Menu)( int & );
fn_ptr_Menu = MenuChoice;
void (*fn_ptr_Process)( int & );
fn_ptr_Process = ProcessMenu;
while( again == 'Y' )
{
MenuChoice( menu_choice );
ProcessMenu( menu_choice );
}
//Delete Memory.
for( int i = 0; i < animalcount; i++)
{
delete[] petName[i];
delete[] ownName[i];
delete[] petType[i];
}
system( "pause" );
return 0;
}
/***********************************************************************************************************************
*Name: MenuChoice
*Parameters: &menu_choice
*Return: none
*Purpose: This function is to display the menu to the user.
***********************************************************************************************************************/
void MenuChoice( int &menu_choice )
{
cout << "\t\t\t\n\nMenu\n\n" << endl;
cout << "1) Board a Critter " << endl;
cout << "2) Remove a Critter " << endl;
cout << "3) Display all Critters " << endl;
cout << "4) Count all Critters and Calculate Daily Proceeds " << endl;
cout << "5) Exit " << endl;
cout << "\n\nPlease enter a menu choice, 1 to 5: " ;
cin >> menu_choice;
}
/***********************************************************************************************************************
*Name: ProcessMenu
*Parameters: &menu_choice
*Return: none
*Purpose: This function is to process the menu choice.
***********************************************************************************************************************/
void ProcessMenu( int &menu_choice )
{
//Function Pointer
void (*fn_ptr_disAll)();
fn_ptr_disAll = DisplayAll;
if( menu_choice < 1 || menu_choice > 5 )
{
cout << "\n\nPlease enter a number between 1 and 5! " << endl;
}
else
{
switch ( menu_choice)
{
case 1 ://Get Pet.
{
GetPet( petName, ownName, petType );
break;
}
case 2://Remove Pet
{
DisplayAll();
RemovePet( petName, ownName, petType );
break;
}
case 3://Display all info
{
DisplayAll();
break;
}
case 4://Display totals and avg
{
DisplayAll();
TotalCat( catCount, catCost );
TotalDog( dogCount, dogCost );
TotalDay( overallCost, catCost, dogCost, totalCount) ;
AvgCap(arrayCount);
break;
}
case 5://Exit the program
{
again = Exit( again );
break;
}
}
}
}
/***********************************************************************************************************************
*Name: GetPet
*Parameters: petName, ownName, petType
*Return: none
*Purpose: This function gets the pet info from the user and gets the counts.
***********************************************************************************************************************/
void GetPet( char **& petName, char **& ownName, char **& petType )
{
//buffer.
char buffer[256] = {0};
//temp arrays
petTemp = new char * [animalcount + 1];
ownTemp = new char * [animalcount + 1];
typeTemp = new char * [animalcount + 1];
//addresses for temp
for( int i = 0; i < animalcount; i++ )
{
petTemp[i] = petName[i];
ownTemp[i] = ownName[i];
typeTemp[i] = petType[i];
}
if( animalcount == 12)
{
cout << "\n\nYou cannot board anymore animals! You are at maximum capacity! " << endl;
}
else
{
cout << "Which cage number do you want to add the critter to? ( 1 to 12) ";
cin >> input;
if( input < 1 || input > 12 )
{
cout << "Please input a number between 1 and 12! " << endl;
}
else
{
int k = input - 1;
//delete old information
delete [] petName;
delete [] ownName;
delete [] petType;
//Get input for the Pet Name, Owner name, and Pet Type.
cout << "\n\nPlease input Pet Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, MAX );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
petTemp[k] = new char[strlen( buffer ) + 1];
strcpy( petTemp[k], buffer );
cout << "\n\nPlease input Owner Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer , MAX );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
ownTemp[k] = new char[strlen( buffer ) + 1];
strcpy( ownTemp[k], buffer );
cout << "\n\nPlease input critter type: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, MAX );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
typeTemp[k] = new char[strlen( buffer ) + 1];
strcpy( typeTemp[k], buffer );
//add the new info.
petName = petTemp;
ownName = ownTemp;
petType = typeTemp;
//Add to the counts.
animalcount++;
totalCount ++;
//Add count to the avg array function helper.
* arrayCount = totalCount;
arrayCount++;
//cat count.
_strlwr( *petType );
char * breaker[10]= {0};
* breaker = petType[k];
int result;
result = strcmp( * breaker, "cat" );
int result1;
result1 = strcmp( * breaker, "dog" );
if( result == 0 )
{
catCount++;
}
if( result1 == 0 )
{
//dog count.
dogCount++;
}
cout << "\n\nCritter " << input << ", has been added! " << endl;
}
}
}
/***********************************************************************************************************************
*Name: DisplayAll
*Parameters: none
*Return: none
*Purpose: This function displays all pet infomation to the user.
***********************************************************************************************************************/
void DisplayAll()
{
cout.setf( ios::left );
cout << setw(10) << "Cage Num." << setw(20) << "Pet Name" << setw(20) << "Owner's Name" << setw(20) << "Pet Type" << endl;
for( int i = 0; i < totalCount; i++ )
{
cout << setw(10) << i+1 << setw(20) << petName[i] << setw(20) << ownName[i] << setw(20) << petType[i] << endl;
}
}
/***********************************************************************************************************************
*Name: RemovePet
*Parameters: petName, ownName, petType
*Return: none
*Purpose: This function displays all pet infomation to the user.
***********************************************************************************************************************/
void RemovePet( char **& petName, char **& ownName, char **& petType )
{
cout << "Which cage number do you want to remove the critter from? ( 1 to 12) ";
cin >> input;
int j = input - 1;
//delete old information
delete [] petName[j];
delete [] ownName[j];
delete [] petType[j];
strcpy( petName[j], "Empty" );
strcpy( ownName[j], "Empty" );
strcpy( petType[j], "Empty" );
//Correct the count
animalcount--;
cout << "\n\nCritter " << input << ", has been removed. " << endl;
}
/***********************************************************************************************************************
*Name: Exit
*Parameters: again
*Return: none
*Purpose: This function exits the program.
***********************************************************************************************************************/
char Exit( char again )
{
again = 'n';
return again;
}
/***********************************************************************************************************************
*Name: TotalCat
*Parameters: int &catCount, int &catCost
*Return: none
*Purpose: This function finds the cat costs and displays.
***********************************************************************************************************************/
void TotalCat( int &catCount, int &catCost )
{
catCost = catCount * CAT;
cout << "\n\nThe Amount of Cats today is: " << catCount << ". " << endl;
cout << "The Sum of today's Cat earnings is: " << catCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: TotalDog
*Parameters: petType
*Return: none
*Purpose: This function finds the dog costs and displays.
***********************************************************************************************************************/
void TotalDog( int &dogCount, int &dogCost )
{
dogCost = dogCount * DOG;
cout << "\n\nThe Amount of Dogs today is: " << dogCount << ". " << endl;
cout << "The Sum of today's Dog earnings is: " << dogCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: TotalDay
*Parameters: int &overallCost, int &catCost, int &dogCost, int &animalcount
*Return: none
*Purpose: This function finds the total for the day.
***********************************************************************************************************************/
void TotalDay( int &overallCost, int &catCost, int &dogCost, int &totalCount )
{
overallCost = catCost + dogCost;
cout << "\n\nThe Total Amount of Critters today is: " << totalCount << ". " << endl;
cout << "Total amount of animals right now: " << animalcount << ". " << endl;
cout << "The Sum of today's earnings is: " << overallCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: AvgCap
*Parameters: none
*Return: none
*Purpose: This function finds the total avg for the day of animals.
***********************************************************************************************************************/
void AvgCap( int * &arrayCount )
{
int avg = 0;
int sum = 0;
arrayCount = &count[0];
for( int i = 0; i < totalCount; i++, arrayCount++ )
{
sum += * arrayCount;
}
avg = sum / totalCount;
cout << "\n\nThe Average Amount of Critters today is: " << avg << ". " << endl;
}
-
June 10th, 2009, 01:11 AM
#4
Re: Access Violation Error Help
Originally Posted by Shadow_Govt
Alright. been messing with it a little bit and got most of it to work. I am leaking memory somewhere; cant figure it out.
1) Have you used a debugger?
2) Do you see something wrong here?
Code:
//delete old information
delete [] petName[j];
delete [] ownName[j];
delete [] petType[j];
strcpy( petName[j], "Empty" );
strcpy( ownName[j], "Empty" );
strcpy( petType[j], "Empty" );
You've deleted petName[j], petOwner[j], etc. but then you start to write characters to the deleted memory. Why are you deleting the information? Why not just overwrite the information with the string "Empty" instead of deleting it?
This is something that I have been informed by my instructor as part of the learning process; vectors, structs, blah, blah, will come later next term.
Sigh. Another bunch of students being taught C++ improperly. Not only is there the lack of usage of things that have been in C++ for over a decade now such as std::string and std::vector, you have this:
Code:
//Function Pointers
void (*fn_ptr_Menu)( int & );
fn_ptr_Menu = MenuChoice;
void (*fn_ptr_Process)( int & );
fn_ptr_Process = ProcessMenu;
Function pointers? Nope, you're learning 'C', which really does very little in learning C++. I would be bold and say you've wasted your money/time in the first semester (unless you want to write 'C' code), as all of this type of coding is discouraged when writing C++ programs.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; June 10th, 2009 at 01:21 AM.
-
June 10th, 2009, 08:07 PM
#5
Re: Access Violation Error Help
I tried the strcpy for just the info, that still causes an error in the heap.
-
June 10th, 2009, 08:19 PM
#6
Re: Access Violation Error Help
Originally Posted by Shadow_Govt
I tried the strcpy for just the info, that still causes an error in the heap.
I pointed out a glaring error. In no way was it guranteed to fix your entire program, however, it still was incorrect.
So do you see the headaches this type of coding produces? This is exactly why C++ was invented, so as to avert this type of memory management and handling.
Regards,
Paul McKenzie
-
June 10th, 2009, 08:29 PM
#7
Re: Access Violation Error Help
as I am going through the debugging, I am noticing "<bad ptr>" on all my new chars. Why would it do this? Is that what is causing this heap assertion?
-
June 10th, 2009, 08:29 PM
#8
Re: Access Violation Error Help
Also, maybe you should just write your own string and vector class. At the very least, all of that memory management would be localized instead of strewn about all over your code now.
You are allocating one place, deleting far from where the original allocation was done, and attempting to keep track of all of this with global variables. That is almost a guarantee things will not work.
You also did not answer my question about using a debugger. No programmer can write such code as you have without using a debugger.
Regards,
Paul McKenzie
-
June 10th, 2009, 08:31 PM
#9
Re: Access Violation Error Help
Originally Posted by Shadow_Govt
as I am going through the debugging, I am noticing "<bad ptr>" on all my new chars. Why would it do this? Is that what is causing this heap assertion?
You have multiple places with "new char". Where exactly are you refering to?
Regards,
Paul McKenzie
-
June 10th, 2009, 08:35 PM
#10
Re: Access Violation Error Help
Also, what is your input that reproduces the error? You didn't mention what menu option(s) you selected to reproduce the error.
Another thing:
Code:
char ** petName = new char * [12];
char ** ownName = new char * [12];
char ** petType = new char * [12];
Why is this being dynamically allocated? You know you have a maximumof 12, so just declare a normal array.
Code:
char *petName[12];
char *ownName[12];
char *petType [12];
Regards,
Paul McKenzie
Last edited by Paul McKenzie; June 10th, 2009 at 08:39 PM.
-
June 10th, 2009, 09:55 PM
#11
Re: Access Violation Error Help
One of my requirements; Dynamically Allocated ragged arrays. Same with the function pointers. I know now that it has something to do with the buffer. While I was going through the debugging process, I noticed that as I was steping over, at the end of the program the buffer was filled with a very strange symbol. Almost like a bass music symbol.
-
June 10th, 2009, 10:22 PM
#12
Re: Access Violation Error Help
Originally Posted by Shadow_Govt
One of my requirements; Dynamically Allocated ragged arrays.
You never delete those arrays at the end of the program. That loop at the end of main() only deletes the individual entries in the array. Also, I see nothing "ragged". A ragged array would be one where one row has 5 entries, another row in the same array has 10 entries, etc. I don't see that going on at all in your program with that array. It's always going to be 12 slots for all three entries.
Secondly, if they are really "ragged", then why are you starting out immediately dynamically allocating them? They should only be allocated when necessary.
Code:
char ** petName = 0;
char ** ownName = 0;
char ** petType = 0;
And then when you add an entry, then and only then do you resize them.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; June 10th, 2009 at 10:25 PM.
-
June 10th, 2009, 10:28 PM
#13
Re: Access Violation Error Help
Code:
void GetPet( char **& petName, char **& ownName, char **& petType )
{
//buffer.
char buffer[256] = {0};
//temp arrays
petTemp = new char * [animalcount + 1];
ownTemp = new char * [animalcount + 1];
typeTemp = new char * [animalcount + 1];
//addresses for temp
for( int i = 0; i < animalcount; i++ )
{
petTemp[i] = petName[i];
ownTemp[i] = ownName[i];
typeTemp[i] = petType[i];
}
if( animalcount == 12)
This code is backwards. You should be testing first for the animal count. If it's 12, then you return. Then you go about and do all of the allocations only if the animalcount is less than 12.
It would also help you if you wrote functions to do the string and array resizing, instead of what you have now. Here is an example (not tested).
Code:
char *AssignNewString(const char* oldString, const char *newString)
{
if ( !oldString || !newString )
return 0;
unsigned int newSize = strlen(newString);
char *pTemp = new char [newSize+1];
pTemp = strlen(oldString + 1);
unsigned int nLenStr = strlen(oldString);
unsigned int minStringSize = min(nLenStr, newSize);
strncpy(pTemp, oldString, minStringSize);
pTemp[minStringSize] = '\0';
delete [] oldString;
return pTemp;
}
Then you call this instead of doing the gymnastics you're going through now with those global temp pointers, etc.
So instead of this:
Code:
//delete old information
delete [] petName;
delete [] ownName;
delete [] petType;
//Get input for the Pet Name, Owner name, and Pet Type.
cout << "\n\nPlease input Pet Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, MAX );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
petTemp[k] = new char[strlen( buffer ) + 1];
strcpy( petTemp[k], buffer );
delete [] oldString
It becomes this:
Code:
cout << "\n\nPlease input Pet Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, MAX );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
petName[k] = AssignNewString( petName[k], buffer);
The function is responsible for resizing the entry. If there is a problem, the code for getting you new string data is localized to that function. You then do a similar function for the arrays themselves.
Regards,
Paul McKenzie
Last edited by Paul McKenzie; June 10th, 2009 at 10:46 PM.
-
June 10th, 2009, 10:42 PM
#14
Re: Access Violation Error Help
here is what I got now:
Code:
#define _CRTDBG_MAP_ALLOC
#include < iostream >
#include < iomanip >
#include < cctype >
#include < cstring >
using std::cout;
using std::cin;
using std::endl;
using std::setw;
using namespace std;
//Variables
const int MAX = 60;
const int CAT = 20;
const int DOG = 35;
int menu_choice;
char again = 'Y';
char ** petName = 0;
char ** petTemp = 0;
char ** ownName = 0;
char ** ownTemp = 0;
char ** petType = 0;
char ** typeTemp = 0;
int animalcount = 0;
int catCount = 0;
int dogCount = 0;
int totalCount = 0;
int count[60] = {0};
int * arrayCount = &count[0];
int catCost = 0;
int dogCost = 0;
int overallCost = 0;
int input = 0;
//Functions
void MenuChoice( int &menu_choice );
void ProcessMenu( int &menu_choice );
void GetPet( char **& petName, char **& ownName, char **& petType );
void DisplayAll();
void RemovePet( char **& petName, char **& ownName, char **& petType );
void TotalCat( int &catCount, int &catCost );
void TotalDog( int &dogCount, int &dogCost );
void TotalDay( int &overallCost, int &catCost, int &dogCost, int &totalCount );
void AvgCap( int * &arrayCount );
char Exit( char again );
int main()
{
//Test for Leaks.
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
//Memory Allocation
petName = new char * [256];
ownName = new char * [256];
petType = new char * [256];
//Function Pointers
void (*fn_ptr_Menu)( int & );
fn_ptr_Menu = MenuChoice;
void (*fn_ptr_Process)( int & );
fn_ptr_Process = ProcessMenu;
while( again == 'Y' )
{
fn_ptr_Menu( menu_choice );
fn_ptr_Process( menu_choice );
}
//Delete Memory.
for( int i = 0; i < totalCount + 1; i++)
{
delete[] petName[i];
delete[] ownName[i];
delete[] petType[i];
delete[] petTemp[i];
delete[] ownTemp[i];
delete[] typeTemp[i];
}
delete[] petName;
delete[] ownName;
delete[] petType;
delete[] petTemp;
delete[] ownTemp;
delete[] typeTemp;
system( "pause" );
return 0;
}
/***********************************************************************************************************************
*Name: MenuChoice
*Parameters: &menu_choice
*Return: none
*Purpose: This function is to display the menu to the user.
***********************************************************************************************************************/
void MenuChoice( int &menu_choice )
{
cout << "\t\t\t\n\nMenu\n\n" << endl;
cout << "1) Board a Critter " << endl;
cout << "2) Remove a Critter " << endl;
cout << "3) Display all Critters " << endl;
cout << "4) Count all Critters and Calculate Daily Proceeds " << endl;
cout << "5) Exit " << endl;
cout << "\n\nPlease enter a menu choice, 1 to 5: " ;
cin >> menu_choice;
}
/***********************************************************************************************************************
*Name: ProcessMenu
*Parameters: &menu_choice
*Return: none
*Purpose: This function is to process the menu choice.
***********************************************************************************************************************/
void ProcessMenu( int &menu_choice )
{
//Function Pointer
void (*fn_ptr_disAll)();
fn_ptr_disAll = DisplayAll;
if( menu_choice < 1 || menu_choice > 5 )
{
cout << "\n\nPlease enter a number between 1 and 5! " << endl;
}
else
{
switch ( menu_choice)
{
case 1 ://Get Pet.
{
GetPet( petName, ownName, petType );
break;
}
case 2://Remove Pet
{
fn_ptr_disAll();
RemovePet( petName, ownName, petType );
break;
}
case 3://Display all info
{
fn_ptr_disAll();
break;
}
case 4://Display totals and avg
{
TotalCat( catCount, catCost );
TotalDog( dogCount, dogCost );
TotalDay( overallCost, catCost, dogCost, totalCount) ;
AvgCap(arrayCount);
break;
}
case 5://Exit the program
{
again = Exit( again );
break;
}
}
}
}
/***********************************************************************************************************************
*Name: GetPet
*Parameters: petName, ownName, petType
*Return: none
*Purpose: This function gets the pet info from the user and gets the counts.
***********************************************************************************************************************/
void GetPet( char **& petName, char **& ownName, char **& petType )
{
if( animalcount == 12)
{
cout << "\n\nYou cannot board anymore animals! You are at maximum capacity! " << endl;
}
else
{
//buffer.
char buffer[MAX] = {0};
//temp arrays
petTemp = new char * [animalcount + 1];
ownTemp = new char * [animalcount + 1];
typeTemp = new char * [animalcount + 1];
//addresses for temp
for( int i = 0; i < animalcount; i++ )
{
petTemp[i] = petName[i];
ownTemp[i] = ownName[i];
typeTemp[i] = petType[i];
}
cout << "Which cage number do you want to add the critter to? ( 1 to 12) ";
cin >> input;
if( input < 1 || input > 12 )
{
cout << "Please input a number between 1 and 12! " << endl;
}
else
{
int k = input - 1;
//delete old information
delete [] petName;
delete [] ownName;
delete [] petType;
//Get input for the Pet Name, Owner name, and Pet Type.
cout << "\n\nPlease input Pet Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, 20 );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
petTemp[k] = new char[strlen( buffer ) + 1];
strcpy( petTemp[k], buffer );
strcpy( buffer, " " );
cout << "\n\nPlease input Owner Name: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer , 20 );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
ownTemp[k] = new char[strlen( buffer ) + 1];
strcpy( ownTemp[k], buffer );
strcpy( buffer, " " );
cout << "\n\nPlease input critter type: ";
cin.ignore( cin.rdbuf()->in_avail() );
cin.getline( buffer, 10 );
cin.clear();
cin.ignore( cin.rdbuf()->in_avail() );
typeTemp[k] = new char[strlen( buffer ) + 1];
strcpy( typeTemp[k], buffer );
strcpy( buffer, " " );
//add the new info.
petName = petTemp;
ownName = ownTemp;
petType = typeTemp;
//Add to the counts.
animalcount++;
totalCount ++;
//Add count to the avg array function helper.
* arrayCount = totalCount;
arrayCount++;
//cat count.
_strlwr( *petType );
char * breaker[10]= {0};
* breaker = petType[k];
int result;
result = strcmp( * breaker, "cat" );
int result1;
result1 = strcmp( * breaker, "dog" );
if( result == 0 )
{
catCount++;
}
if( result1 == 0 )
{
//dog count.
dogCount++;
}
cout << "\n\nCritter " << input << ", has been added! " << endl;
}
}
}
/***********************************************************************************************************************
*Name: DisplayAll
*Parameters: none
*Return: none
*Purpose: This function displays all pet infomation to the user.
***********************************************************************************************************************/
void DisplayAll()
{
cout.setf( ios::left );
cout << setw(10) << "Cage Num." << setw(20) << "Pet Name" << setw(20) << "Owner's Name" << setw(20) << "Pet Type" << endl;
for( int i = 0; i < totalCount; i++ )
{
cout << setw(10) << i+1 << setw(20) << petName[i] << setw(20) << ownName[i] << setw(20) << petType[i] << endl;
}
}
/***********************************************************************************************************************
*Name: RemovePet
*Parameters: petName, ownName, petType
*Return: none
*Purpose: This function displays all pet infomation to the user.
***********************************************************************************************************************/
void RemovePet( char **& petName, char **& ownName, char **& petType )
{
cout << "Which cage number do you want to remove the critter from? ( 1 to 12) ";
cin >> input;
int j = input - 1;
//delete old information
delete [] petName[j];
delete [] ownName[j];
delete [] petType[j];
strcpy( petName[j], "Empty" );
strcpy( ownName[j], "Empty" );
strcpy( petType[j], "Empty" );
//Correct the count
animalcount--;
cout << "\n\nCritter " << input << ", has been removed. " << endl;
}
/***********************************************************************************************************************
*Name: Exit
*Parameters: again
*Return: none
*Purpose: This function exits the program.
***********************************************************************************************************************/
char Exit( char again )
{
again = 'n';
return again;
}
/***********************************************************************************************************************
*Name: TotalCat
*Parameters: int &catCount, int &catCost
*Return: none
*Purpose: This function finds the cat costs and displays.
***********************************************************************************************************************/
void TotalCat( int &catCount, int &catCost )
{
catCost = catCount * CAT;
cout << "\n\nThe Amount of Cats today is: " << catCount << ". " << endl;
cout << "The Sum of today's Cat earnings is: " << catCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: TotalDog
*Parameters: petType
*Return: none
*Purpose: This function finds the dog costs and displays.
***********************************************************************************************************************/
void TotalDog( int &dogCount, int &dogCost )
{
dogCost = dogCount * DOG;
cout << "\n\nThe Amount of Dogs today is: " << dogCount << ". " << endl;
cout << "The Sum of today's Dog earnings is: " << dogCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: TotalDay
*Parameters: int &overallCost, int &catCost, int &dogCost, int &animalcount
*Return: none
*Purpose: This function finds the total for the day.
***********************************************************************************************************************/
void TotalDay( int &overallCost, int &catCost, int &dogCost, int &totalCount )
{
overallCost = catCost + dogCost;
cout << "\n\nThe Total Amount of Critters today is: " << totalCount << ". " << endl;
cout << "Total amount of animals right now: " << animalcount << ". " << endl;
cout << "The Sum of today's earnings is: " << overallCost << ". " << endl;
}
/***********************************************************************************************************************
*Name: AvgCap
*Parameters: none
*Return: none
*Purpose: This function finds the total avg for the day of animals.
***********************************************************************************************************************/
void AvgCap( int * &arrayCount )
{
int avg = 0;
int sum = 0;
arrayCount = &count[0];
for( int i = 0; i < totalCount; i++, arrayCount++ )
{
sum += * arrayCount;
}
avg = sum / totalCount;
cout << "\n\nThe Average Amount of Critters today is: " << avg << ". " << endl;
}
I am getting "debug assertion" and if I start the program and try to exit without doing anything I get:
Unhandled exception at 0x62f831ea (msvcr90d.dll) in Final.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.
Last edited by Shadow_Govt; June 10th, 2009 at 10:49 PM.
-
June 10th, 2009, 10:47 PM
#15
Re: Access Violation Error Help
Your right! Thanks for pointing that out.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|