Слишком маленький буфер во время строительства объекта. Думаю, это как-то связано с strcpy_s ()

Код, который я выкладываю, является результатом третьей недели работы над этим классом. Я довольно хорошо разбирался в вещах (или я так думал), но на этой неделе я сосредоточился на указателях, и я не знаю, почему я продолжаю получать эту ошибку. Я продолжаю получать Отладочное утверждение не удалось! ошибка вместе с общим объяснением «Буфер слишком мал».

мое сообщение об ошибке

Вот полный код, который я собираю на ОС Win8 с использованием VS 2012 RC версии 11.0.505221.1. Единственное отличие от того, что я скомпилировал в Linux, заключается в том, что я использую в этом коде strcpy_s (), потому что по какой-то причине MS не любит strcpy ().

#include "stdafx.h"#include <iostream>
#include <string>
#include <iomanip>
#include <limits>

using namespace std;

class HotelRoom
{
char roomNumber[4];
char guest[81];
int roomCapacity, currentOccupants;
double roomRate;

public:
HotelRoom(char[], char[], int, double);
~HotelRoom();
void DisplayRoom();
void DisplayNumber();
void DisplayName();
int GetCapacity();
int GetStatus();
double GetRate();
void ChangeStatus(int);
void ChangeRate(double);
};

HotelRoom::~HotelRoom() {
cout << endl << endl;
cout << "Room #" << roomNumber << " no longer exists." << endl;
delete [] guest;
}

void HotelRoom::DisplayName() {
cout << guest;
}

void HotelRoom::DisplayNumber() {
cout << roomNumber;
}

int HotelRoom::GetCapacity() {
return roomCapacity;
}

int HotelRoom::GetStatus() {
return currentOccupants;
}

double HotelRoom::GetRate() {
return roomRate;
}

void HotelRoom::ChangeStatus(int occupants) {
if(occupants <= roomCapacity) {
currentOccupants = occupants;
}
else {
cout << endl << "There are too many people for this room. Setting occupancy to -1." << endl;
currentOccupants = -1;
}
}

void HotelRoom::ChangeRate(double rate) {
roomRate = rate;
}

HotelRoom::HotelRoom(char room[], char guestName[], int capacity, double rate)
{
strcpy_s(roomNumber, room);     //Compiles fine with strcpy on Linux, but MS is making me use strcpy_s to compile
guestName = new char[strlen(guestName) + 1];
strcpy_s(guest, guestName);     //Same as above
roomCapacity     =  capacity;
currentOccupants = 0;
roomRate         = rate;
}

void HotelRoom::DisplayRoom()
{
cout << setprecision(2)
<< setiosflags(ios::fixed)
<< setiosflags(ios::showpoint);
cout << endl << "The following is pertinent data relating to the room:\n"<< "Guest Name:        " << guest << endl
<< "Room Number:       " << roomNumber << endl
<< "Room Capacity:     " << GetCapacity() << endl
<< "Current Occupants: " << GetStatus() << endl
<< "Room Rate:         $" << GetRate() << endl;
}int main()
{
int numOfGuests;
char roomNum[4];
char buffer[81];    //Buffer to store guest's name
int roomCap;
double roomRt;
bool badInput = true;
cout << endl << "Please enter the 3-digit room number: ";
do {        //loop to check user input
badInput = false;
for(int x = 0; x < 3; x++)
{
cin >> roomNum[x];
if(!isdigit(roomNum[x]))        //check all chars entered are digits
{
badInput = true;
}
}
char x = cin.get();
if(x != '\n')       //check that only 3 chars were entered
{
badInput = true;
}
if(badInput)
{
cout << endl << "You did not enter a valid room number. Please try again: ";
}
} while(badInput);
for(;;)     //Infinite loop broken when correct input obtained
{
cout << "Please enter the room capacity: ";
if(cin >> roomCap) {
break;
} else {
cout << "Please enter a valid integer" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
for(;;)     //Infinite loop broken when correct input obtained
{
cout << "Please enter the nightly room rate: ";
if(cin >> roomRt) {
break;
} else {
cout << "Please enter a valid rate" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
cin.get();      //Dump the trailing return character
cout << "Please enter guest name: ";
cin.getline(buffer, 81);
HotelRoom room1(roomNum, buffer, roomCap, roomRt);
for (;;) {      //Infinite loop broken when correct input obtained
cout << "Please enter the number of guests for room #";
room1.DisplayNumber();
cout << ": ";
if (cin >> numOfGuests) {
break;
} else {
cout << "Please enter a valid integer" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
room1.ChangeStatus(numOfGuests);
room1.DisplayRoom();
cout << endl << "The following shows after the guests have checked out." << endl;
room1.ChangeStatus(0);
room1.DisplayRoom();
room1.ChangeRate(175.0);
for (;;) {      //Infinite loop broken when correct input obtained
cout << "Please enter the number of guests for room #";
room1.DisplayNumber();
cout << ": ";
if (cin >> numOfGuests) {
break;
} else {
cout << "Please enter a valid integer" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
room1.ChangeStatus(numOfGuests);
room1.DisplayRoom();
return 0;
}

ОБНОВИТЬ:

Я добавил операторы cout, чтобы увидеть, где проблема возникает в программе, и это определенно есть в операторах strcpy () в конструкторе HotelRoom. Вот конструктор, а следующий вывод, который я получил

HotelRoom::HotelRoom(char room[], char guestName[], int capacity, double rate)
{
cout << endl << "Attempting 1st strcpy...";
strcpy_s(roomNumber, room);     //Compiles fine with strcpy on Linux, but MS is making me use strcpy_s to compile
cout << endl << "1st strcpy successful!";
guestName = new char[strlen(guestName) + 1];
cout << endl << "Attempting 2nd strcpy...";
strcpy_s(guest, guestName);     //Same as above
cout << endl << "2nd strcpy successful!";
roomCapacity     =  capacity;
currentOccupants = 0;
roomRate         = rate;
}

выход cout

1

Решение

Я думаю, что вам может понадобиться посмотреть на это снова:

guestName = new char[strlen(guestName) + 1];
cout << endl << "Attempting 2nd strcpy...";
strcpy_s(guest, guestName);     //Same as above

Я уверен, так как guestName[] является параметром, вы намеревались НЕ потерять этот указатель навсегда в области действия функции, заменив его недавно выделенным, не завершенным указателем, а затем продолжив копировать неинициализированную память в переменную-член.

Возможно, вы хотели это вместо этого:

strcpy_s(guest, guestName);

Также, guest является переменной-членом типа char[81], если вы не хотите, чтобы менеджер кучи снова вызывал этот неприятный диалог, вы можете избежать этого в деструкторе класса:

delete [] guest;

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

1

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

Вы определили char buffer[81], но вы пытаетесь прочитать 81 символов cin.getline(buffer, 81) исключая \0, Таким образом, вы должны изменить ранее char buffer[82] или позже один cin.getline(buffer, 80),

И если вы используете C ++, почему бы не использовать string?

0

Причина, по которой MS просит вас использовать функцию _s, состоит в том, чтобы защитить ваш код от переполнения буфера, как ваш код в настоящее время отображает. Проверьте эта ссылка для дополнительной информации.

У вас есть строка из 81 символа. Вы создаете новую строку размером + 1 (вы потеряете ваши данные), которая теперь составляет 82 символа. Когда вы пытаетесь скопировать ваш буфер в гостевой файл длиной 81 символ, вы получаете утверждение.

Подумайте об использовании std :: string и прекратите выделять / освобождать строки, в вашем случае это бесполезно.

0

Если вы не используете strcpy_s Вы должны выполнить проверку границ перед копированием из указателя в буфер.

Также не стоит называть удаление на guest, Удалить используется для освобождения памяти, выделенной вами с помощью новой.

0
По вопросам рекламы [email protected]