2017-12-18 90 views
0

当我尝试编译我的代码,我得到MS4:免费()无效指针0xb74e74e0 ***

* glibc的检测* MS4:免费()无效指针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

您试图解除分配无效的内存块。 – chris

+0

谢谢你解释克里斯,我该如何解决这个问题? – Jsil

+0

使用调试器或内存工具(如valgrind或消毒工具)来确定崩溃发生的位置,并对该指针的无效值进行一些调查。重现问题的程序越小,就越容易这样做。 – chris

回答

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指针来避免。

+0

谢谢。我从你所说的话中增加了m_name = nullptr;到复制构造函数和之前(cName!= nullptr) 编辑:修复了这个问题,谢谢。 – Jsil