[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
2022-01-19 16:48:02
質問
malloc: *** error for object 0x10ee008c0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
あるいは、すべてを印刷しようとすると、次のようになります。
Segmentation fault: 11
OOPの授業の宿題をやっているのですが、もう1時間くらい詰まっています。キーボード入力を十分に使ったところで、このようなエラーが発生しています。私は全くイライラしない人間なのですが、ここにきて非常にイライラしています。以下がそのファイルです。
これは本のクラスです。これはとてもしっかりしていると思います。でも、一応参考までに。
//--------------- BOOK.CPP ---------------
// The class definition for Book.
//
#include <iostream>
#include "book.h"
using namespace std;
Book::Book()
//
{
strcpy(title, " ");
strcpy(author, " ");
type = FICTION;
price = 0;
}
void Book::Set(const char* t, const char* a, Genre g, double p)
{
strcpy(title, t);
strcpy(author, a);
type = g;
price = p;
}
const char* Book::GetTitle() const
{
return title;
}
const char* Book::GetAuthor() const
{
return author;
}
double Book::GetPrice() const
{
return price;
}
Genre Book::GetGenre() const
{
return type;
}
void Book::Display() const
{
int i;
cout << GetTitle();
for (i = strlen(title) + 1; i < 32; i++)
cout << (' ');
cout << GetAuthor();
for (i = strlen(author) + 1; i < 22; i++)
cout << (' ');
switch (GetGenre())
{
case FICTION:
cout << "Fiction ";
break;
case MYSTERY:
cout << "Mystery ";
break;
case SCIFI:
cout << "SciFi ";
break;
case COMPUTER:
cout << "Computer ";
break;
}
cout << "$";
if (GetPrice() < 1000)
cout << " ";
if (GetPrice() < 100)
cout << " ";
if (GetPrice() < 10)
cout << " ";
/* printf("%.2f", GetPrice());*/
cout << '\n';
}
これは、配列とダイナミックアロケーションを扱うストアクラスです。これは入力コマンドを使わなくても、その関数を使うだけでうまく動作していました。
//--------------- STORE.CPP ---------------
// The class definition for Store.
//
#include <iostream>
#include <cstring> // for strcmp
#include "store.h"
using namespace std;
Store::Store()
{
maxSize = 5;
currentSize = 0;
bookList = new Book[maxSize];
}
Store::~Store()
// This destructor function for class Store
// deallocates the Store's list of Books
{
delete [] bookList;
}
void Store::Insert(const char* t, const char* a, Genre g, double p)
// Insert a new entry into the direrctory.
{
if (currentSize == maxSize)// If the directory is full, grow it.
Grow();
bookList[currentSize++].Set(t, a, g, p);
}
void Store::Sell(const char* t)
// Sell a book from the store.
{
char name[31];
strcpy(name, t);
int thisEntry = FindBook(name);// Locate the name in the directory.
if (thisEntry == -1)
cout << *name << " not found in directory";
else
{
cashRegister = cashRegister + bookList[thisEntry].GetPrice();
// Shift each succeding element "down" one position in the
// Entry array, thereby deleting the desired entry.
for (int j = thisEntry + 1; j < currentSize; j++)
bookList[j - 1] = bookList[j];
currentSize--;// Decrement the current number of entries.
cout << "Entry removed.\n";
if (currentSize < maxSize - 5)// If the directory is too big, shrink it.
Shrink();
}
}
void Store::Find(const char* x) const
// Display the Store's matches for a title or author.
{
// Prompt the user for a name to be looked up
char name[31];
strcpy(name, x);
int thisBook = FindBook(name);
if (thisBook != -1)
bookList[thisBook].Display();
int thisAuthor = FindAuthor(name, true);
if ((thisBook == -1) && (thisAuthor == -1))
cout << name << " not found in current directory\n";
}
void Store::DisplayGenre(const Genre g) const
{
double genrePrice = 0;
int genreCount = 0;
for (int i = 0; i < currentSize; i++)// Look at each entry.
{
if (bookList[i].GetGenre() == g)
{
bookList[i].Display();
genrePrice = genrePrice + bookList[i].GetPrice();
genreCount++;
}
}
cout << "Number of books in this genre: " << genreCount
<< " " << "Total: $";
if (genrePrice < 1000)
cout << " ";
if (genrePrice < 100)
cout << " ";
if (genrePrice < 10)
cout << " ";
printf("%.2f", genrePrice);
}
void Store::DisplayStore() const
{
if (currentSize >= 1)
{
cout << "**Title**\t\t"
<< "**Author**\t"
<< "**Genre**\t"
<< "**Price**\n\n";
for (int i = 0; i < currentSize; i++)
bookList[i].Display();
}
else
cout << "No books currently in inventory\n\n";
cout << "Total Books = " << currentSize
<< "\nMoney in the register = $";
if (cashRegister < 1000)
cout << " ";
if (cashRegister < 100)
cout << " ";
if (cashRegister < 10)
cout << " ";
printf("%.2f", cashRegister);
cout << '\n';
}
void Store::Sort(char type)
{
Book temp;
for(int i = 0; i <= currentSize; i++)
{
for (int j = i+1; j < currentSize; j++)
{
if (type == 'A')
{
if (strcmp(bookList[i].GetTitle(), bookList[j].GetTitle()) > 0)
{
temp = bookList[i];
bookList[i] = bookList[j];
bookList[j] = temp;
}
}
if (type == 'T')
{
if (strcmp(bookList[i].GetAuthor(), bookList[j].GetAuthor()) > 0)
{
temp = bookList[i];
bookList[i] = bookList[j];
bookList[j] = temp;
}
}
}
}
}
void Store::SetCashRegister(double x)
// Set value of cash register
{
cashRegister = x;
}
void Store::Grow()
// Double the size of the Store's bookList
// by creating a new, larger array of books
// and changing the store's pointer to refer to
// this new array.
{
maxSize = currentSize + 5;// Determine a new size.
cout << "** Array being resized to " << maxSize
<< " allocated slots" << '\n';
Book* newList = new Book[maxSize];// Allocate a new array.
for (int i = 0; i < currentSize; i++)// Copy each entry into
newList[i] = bookList[i];// the new array.
delete [] bookList;// Remove the old array
bookList = newList;// Point old name to new array.
}
void Store::Shrink()
// Divide the size of the Store's bookList in
// half by creating a new, smaller array of books
// and changing the store's pointer to refer to
// this new array.
{
maxSize = maxSize - 5;// Determine a new size.
cout << "** Array being resized to " << maxSize
<< " allocated slots" << '\n';
Book* newList = new Book[maxSize];// Allocate a new array.
for (int i = 0; i < currentSize; i++)// Copy each entry into
newList[i] = bookList[i];// the new array.
delete [] bookList;// Remove the old array
bookList = newList;// Point old name to new array.
}
int Store::FindBook(char* name) const
// Locate a name in the directory. Returns the
// position of the entry list as an integer if found.
// and returns -1 if the entry is not found in the directory.
{
for (int i = 0; i < currentSize; i++)// Look at each entry.
if (strcmp(bookList[i].GetTitle(), name) == 0)
return i;// If found, return position and exit.
return -1;// Return -1 if never found.
}
int Store::FindAuthor(char* name, const bool print) const
// Locate a name in the directory. Returns the
// position of the entry list as an integer if found.
// and returns -1 if the entry is not found in the directory.
{
int returnValue;
for (int i = 0; i < currentSize; i++)// Look at each entry.
if (strcmp(bookList[i].GetAuthor(), name) == 0)
{
if (print == true)
bookList[i].Display();
returnValue = i;// If found, return position and exit.
}
else
returnValue = -1;// Return -1 if never found.
return returnValue;
}
さて、この人は少し仕事が必要な人です。空白の部分があるかもしれないので、それは無視してください。これは全ての入力を制御しているのですが、これが問題だと思います。
#include <iostream>
#include "store.h"
using namespace std;
void ShowMenu()
// Display the main program menu.
{
cout << "\n\t\t*** BOOKSTORE MENU ***";
cout << "\n\tA \tAdd a Book to Inventory";
cout << "\n\tF \tFind a book from Inventory";
cout << "\n\tS \tSell a book";
cout << "\n\tD \tDisplay the inventory list";
cout << "\n\tG \tGenre summary";
cout << "\n\tO \tSort inventory list";
cout << "\n\tM \tShow this Menu";
cout << "\n\tX \teXit Program";
}
char GetAChar(const char* promptString)
// Prompt the user and get a single character,
// discarding the Return character.
// Used in GetCommand.
{
char response;// the char to be returned
cout << promptString;// Prompt the user
cin >> response;// Get a char,
response = toupper(response);// and convert it to uppercase
cin.get();// Discard newline char from input.
return response;
}
char Legal(char c)
// Determine if a particular character, c, corresponds
// to a legal menu command. Returns 1 if legal, 0 if not.
// Used in GetCommand.
{
return((c == 'A') || (c == 'F') || (c == 'S') ||
(c == 'D') || (c == 'G') || (c == 'O') ||
(c == 'M') || (c == 'X'));
}
char GetCommand()
// Prompts the user for a menu command until a legal
// command character is entered. Return the command character.
// Calls GetAChar, Legal, ShowMenu.
{
char cmd = GetAChar("\n\n>");// Get a command character.
while (!Legal(cmd))// As long as it's not a legal command,
{// display menu and try again.
cout << "\nIllegal command, please try again . . .";
ShowMenu();
cmd = GetAChar("\n\n>");
}
return cmd;
}
void Add(Store s)
{
char aTitle[31];
char aAuthor[21];
Genre aGenre = FICTION;
double aPrice = 10.00;
cout << "Enter title: ";
cin.getline(aTitle, 30);
cout << "Enter author: ";
cin.getline(aAuthor, 20);
/*
cout << aTitle << " " << aAuthor << "\n";
cout << aGenre << " " << aPrice << '\n';
*/
s.Insert(aTitle, aAuthor, aGenre, aPrice);
}
void Find()
{
}
void Sell()
{
}
void ViewGenre(Store s)
{
char c;
Genre result;
do
c = GetAChar("Enter Genre - (F)iction, (M)ystery, (S)ci-Fi, or (C)omputer: ");
while ((c != 'F') && (c != 'M') && (c != 'S') && (c != 'C'));
switch (result)
{
case 'F': s.DisplayGenre(FICTION); break;
case 'M': s.DisplayGenre(MYSTERY); break;
case 'S': s.DisplayGenre(SCIFI); break;
case 'C': s.DisplayGenre(COMPUTER); break;
}
}
void Sort(Store s)
{
char c;
Genre result;
do
c = GetAChar("Enter Genre - (F)iction, (M)ystery, (S)ci-Fi, or (C)omputer: ");
while ((c != 'A') && (c != 'T'));
s.Sort(c);
}
void Intro(Store s)
{
double amount;
cout << "*** Welcome to Bookstore Inventory Manager ***\n"
<< "Please input the starting money in the cash register: ";
/* cin >> amount;
s.SetCashRegister(amount);*/
}
int main()
{
Store mainStore;// Create and initialize a Store.
Intro(mainStore);//Display intro & set Cash Regsiter
ShowMenu();// Display the menu.
/*mainStore.Insert("A Clockwork Orange", "Anthony Burgess", SCIFI, 30.25);
mainStore.Insert("X-Factor", "Anthony Burgess", SCIFI, 30.25);*/
char command;// menu command entered by user
do
{
command = GetCommand();// Retrieve a command.
switch (command)
{
case 'A': Add(mainStore); break;
case 'F': Find(); break;
case 'S': Sell(); break;
case 'D': mainStore.DisplayStore(); break;
case 'G': ViewGenre(mainStore); break;
case 'O': Sort(mainStore); break;
case 'M': ShowMenu(); break;
case 'X': break;
}
} while ((command != 'X'));
return 0;
}
どうか、どんなことでもご協力をお願いします。 ありがとうございます。
解決方法は?
C++のエキサイティングな世界へようこそ!
簡単な答え:Storeを値として渡している。メニュー関数はすべてStore&かStore*を受け取るようにしましょう。
Storeを値として渡す場合、暗黙のうちにコピーが行われます(したがって、mainStore変数が実際に変更されることはありません)。関数から戻ると、Store::~Storeが呼び出され、コピーされたデータがクリーンアップされます。これにより、実際のポインタ値を変更することなく、mainStore.bookListが解放されます。
さらにメニューを操作すると、メモリが破壊され、何度も二重解放が行われます。
HINT: もしあなたがLinuxを使っているなら、プログラムをvalgrindで実行すれば、ほとんどの簡単なメモリエラーを指摘してくれるでしょう。
関連
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】fpermissiveフラグは何をするのですか?
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み] c++ 解放されるポインタが割り当てられていないエラー
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み] 既に.objで定義されている-二重包含はない
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】'std::cout'への未定義の参照
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された