当我尝试编译代码时,我得到了
*检测到glibc * ms4:free()无效指针0xb74e74e0 ***
错误。我不确定这个错误意味着什么或它发生在哪里。任何有关这方面的帮助将非常感激。谢谢。
NonPerishable.cpp
#include <iostream>
#include <cstring>
#include <fstream>
#include <iomanip>
#include "NonPerishable.h"
#include "ErrorMessage.h"
namespace sict {
using namespace std;
void NonPerishable::name(const char* cName) {
if (m_name != nullptr) {
delete[] m_name;
}
if (cName != nullptr) {
m_name = nullptr;
m_name = new char[strlen(cName) + 1];
strcpy(m_name, cName);
}
}
const char* NonPerishable::name() const {
return m_name;
}
double NonPerishable::cost() const {
double final = m_price;
if (m_taxable) {
final += (m_price * taxRate);
}
return final;
}
void NonPerishable::message(const char* msg) {
this->m_error.message(msg);
}
bool sict::NonPerishable::isClear() const {
return m_error.isClear();
}
NonPerishable::NonPerishable(const char type) {
m_prodType = type;
strcpy(m_sku, "");
m_name = nullptr;
strcpy(m_unit, "");
m_quantity = 0;
m_amountNeeded = 0;
m_price = 0.0;
m_taxable = true;
m_error.clear();
}
NonPerishable::NonPerishable(const char* sku, const char* name, const char* unit, int quantity, bool taxable, double price, int needed) {
m_prodType = 'N';
strcpy(m_sku, sku);
m_name = nullptr;
strcpy(m_unit, unit);
m_quantity = quantity;
m_amountNeeded = needed;
m_price = price;
m_taxable = taxable;
m_error.clear();
this->name(name);
}
NonPerishable::NonPerishable(const NonPerishable& obj) {
m_prodType = 'N';
strcpy(m_sku, obj.m_sku);
strcpy(m_unit, obj.m_unit);
m_quantity = obj.m_quantity;
m_amountNeeded = obj.m_amountNeeded;
m_price = obj.m_price;
m_taxable = obj.m_taxable;
this->name(obj.m_name);
}
NonPerishable& NonPerishable::operator=(const NonPerishable& obj) {
m_prodType = 'N';
strcpy(m_sku, obj.m_sku);
strcpy(m_unit, obj.m_unit);
m_quantity = obj.m_quantity;
m_amountNeeded = obj.m_amountNeeded;
m_price = obj.m_price;
m_taxable = obj.m_taxable;
this->name(obj.m_name);
/*if (!obj.m_error.isClear()) {
m_error.message(obj.m_error.message());
}*/
return *this;
}
NonPerishable::~NonPerishable() {
if (m_name != nullptr) {
delete[] m_name;
}
}
std::fstream& NonPerishable::store(std::fstream& file, bool newLine) const {
if (!isEmpty()) {
file << m_prodType << "," << m_sku << "," << m_name << "," << m_unit << "," << m_quantity << "," << m_amountNeeded << "," << m_price << "," << m_taxable << "," << m_error.message();
if (newLine) {
file << endl;
}
}
return file;
}
std::fstream& NonPerishable::load(std::fstream& file) {
char empty;
file >> m_prodType >> empty >> m_sku >> empty >> m_name >> empty >> m_unit >> empty >> m_quantity >> empty >> m_amountNeeded >> empty >> m_price >> empty >> m_taxable;
return file;
}
std::ostream& NonPerishable::write(std::ostream& os, bool linear) const {
if (!isEmpty()) {
if (linear) {
os << setw(max_sku_length) << m_sku << "|" << setw(20) << m_name << "|" << setw(7) << m_price << "|" << setw(4) << m_quantity << "|" << setw(10) << m_unit << "|" << setw(4) << m_amountNeeded;
}
else {
os << "Sku: " << m_sku << endl
<< "Name: " << m_name << endl
<< "Price: " << m_price << endl;
if (m_taxable) {
os << "Price after tax: " << total_cost() << endl;
}
else {
os << "N/A" << endl;
}
os << "Quantity on Hand: " << m_quantity << endl
<< "Quantity Needed: " << m_amountNeeded << endl;
}
}
return os;
}
std::istream& NonPerishable::read(std::istream& is) {
char tempChar;
bool valid = false;
double tempNum;
int tempInt;
cout << "Sku: ";
is >> m_sku;
cout << "Name: ";
is >> m_name;
cout << "Unit: ";
is >> m_unit;
cout << "Taxed? (y/n): ";
is >> tempChar;
if (tempChar == 'y' || tempChar == 'Y') {
m_taxable = true;
valid = true;
}
if (tempChar == 'n' || tempChar == 'N') {
m_taxable = false;
valid = true;
}
if (!valid) {
is.istream::setstate(std::ios::failbit);
m_error.message("Only (Y)es or (N)o are acceptable");
}
cout << "Price: ";
is >> tempNum;
if (tempNum >= 0) {
m_price = tempNum;
}
if (is.std::ios::fail()) {
m_error.message("Invalid Price Entry");
}
cout << "Quantity on Hand: ";
is >> tempInt;
if (tempInt >= 0) {
m_quantity = tempInt;
}
if (is.std::ios::fail()) {
m_error.message("Invalid Quantity Entry");
}
cout << "Quantity Needed: ";
is >> tempInt;
if (tempInt >= 0) {
m_amountNeeded = tempInt;
}
if (is.std::ios::fail()) {
m_error.message("Invalid Quantity Needed Entry");
}
return is;
}
bool NonPerishable::operator==(const char* sku) const {
if (strcmp(sku, this->m_sku) == 0) {
return true;
}
else {
return false;
}
}
double NonPerishable::total_cost() const {
double total = m_price * m_quantity;
if (m_taxable) {
total += ((m_price * m_quantity) * taxRate);
}
return total;
}
void NonPerishable::quantity(int amount) {
m_quantity = amount;
}
bool NonPerishable::isEmpty() const {
if (m_sku[0] == '\0' && m_name == nullptr && m_unit[0] == '\0' && m_quantity == 0 && m_amountNeeded == 0 && m_price == 0 && m_taxable == true) {
return true;
}
else {
return false;
}
}
int NonPerishable::qtyNeeded() const {
return m_amountNeeded;
}
int sict::NonPerishable::quantity() const {
return m_quantity;
}
bool NonPerishable::operator>(const char* sku) const {
if (m_sku > sku) {
return true;
}
else {
return false;
}
}
int NonPerishable::operator+=(int units) {
if (units > 0) {
m_quantity += units;
m_amountNeeded -= units;
}
return m_quantity;
}
bool NonPerishable::operator>(const Product& obj) const {
if (m_name > obj.name()) {
return true;
}
else {
return false;
}
}
std::ostream& operator<<(std::ostream& os, const Product& obj) {
obj.write(os, true);
return os;
}
std::istream& operator>>(std::istream& is, Product& obj) {
obj.read(is);
return is;
}
double operator+=(double& cost, const Product& obj) {
return (cost + obj.total_cost());
}
Product* CreateProduct() {
Product* temp = nullptr;
temp = new NonPerishable;
return temp;
}
}
NonPerishable.h
#ifndef SICT_NONPERISHABLE_H
#define SICT_NONPERISHABLE_H
#include "Product.h"
#include "ErrorMessage.h"
namespace sict {
const int max_sku_length = 7;
const int max_unit_length = 10;
const int max_name_length = 75;
const double taxRate = 0.13;
class NonPerishable : public Product {
char m_prodType;
char m_sku[max_sku_length];
char* m_name;
char m_unit[max_unit_length];
int m_quantity;
int m_amountNeeded;
double m_price;
bool m_taxable;
ErrorMessage m_error;
protected:
void name(const char* name);
const char* name() const;
double cost() const;
void message(const char* msg);
bool isClear() const;
public:
NonPerishable(const char type = '\0');
NonPerishable(const char* sku, const char* name, const char* unit, int quantity = 0, bool taxable = true, double price = 0, int needed = 0);
NonPerishable(const NonPerishable& obj);
NonPerishable& operator=(const NonPerishable& obj);
~NonPerishable();
std::fstream& store(std::fstream& file, bool newLine = true) const;
std::fstream& load(std::fstream& file);
std::ostream& write(std::ostream& os, bool linear) const;
std::istream& read(std::istream& is);
bool operator==(const char* sku) const;
double total_cost() const;
void quantity(int amount);
bool isEmpty() const;
int qtyNeeded() const;
int quantity() const;
bool operator>(const char* sku) const;
int operator+=(int units);
bool operator>(const Product& obj) const;
};
std::ostream& operator<<(std::ostream& os, const Product& obj);
std::istream& operator>>(std::istream& is, Product& obj);
double operator +=(double& cost, const Product& obj);
Product* CreateProduct();
}
#endif
我曾尝试在网上寻找解决方案,但没有找到任何解决方案。我希望有经验的人可以提供帮助。
答案 0 :(得分:0)
在复制构造函数中
NonPerishable::NonPerishable(const NonPerishable& obj) {
m_prodType = 'N';
strcpy(m_sku, obj.m_sku);
strcpy(m_unit, obj.m_unit);
m_quantity = obj.m_quantity;
m_amountNeeded = obj.m_amountNeeded;
m_price = obj.m_price;
m_taxable = obj.m_taxable;
this->name(obj.m_name);
}
你永远不会初始化m_name
。这可能会导致this->name(obj.m_name);
调用删除未初始化的指针。
同样在name
函数
void NonPerishable::name(const char* cName) {
if (m_name != nullptr) {
delete[] m_name;
}
if (cName != nullptr) {
m_name = nullptr;
m_name = new char[strlen(cName) + 1];
strcpy(m_name, cName);
}
}
如果cName
恰好是nullptr
,您将删除m_name
但不会为其提供新值。这将导致稍后的双重删除,就像在析构函数中一样。
使用std::string
代替char指针可以避免所有这些。