0

I've been pulling my hair out over a certain error that seems to be plaguing my program. I've attempted to search online for cases similar to mine but I can't seem to find a way to apply the other solutions to this problem. My issue is as follows: When I initially open the program it immediately stops responding and crashes. Debugging led me to find the error in question is "0xC0000005: Access violation writing location 0xCCCCCCCC". It seems to be tied to me assigning two attributes (sku_ and name_ ) as '\0'. If I change these values to anything else such as "" or even "\0" the program runs in visual studio, but will fail to compile elsewhere. Could someone help me understand where I am going wrong?

Product.h

#ifndef SICT_Product_H__
#define SICT_Product_H__
#include "general.h"
#include "Streamable.h"
#include <cstring>
namespace sict {
    class Product : public Streamable {
        char sku_ [MAX_SKU_LEN + 1];
        char* name_;
        double price_;
        bool taxed_;
        int quantity_;
        int qtyNeeded_;

        public:
            //Constructors
            Product();
            Product(const char* sku, const char* name1, bool taxed = true, double price = 0, int qtyNeeded =0);
            Product(Product& g);
            ~Product();

            //Putter Functions
            void sku(const char* sku) { strcpy(sku_,sku); };
            void price(double price) {price_ = price;};
            void name(const char* name);
            void taxed(bool taxed) { taxed_ = taxed; };
            void quantity(int quantity) { quantity_ = quantity; };
            void qtyNeeded(int qtyNeeded) { qtyNeeded_ = qtyNeeded; };

            //Getter functions
            const char* sku() const { return sku_; };
            double price() const { return price_; };
           const char* name() const { return name_; };
            bool taxed() const { return taxed_; };
            int quantity() const { return quantity_; };
            int qtyNeeded() const { return qtyNeeded_; };
            double cost() const;
            bool isEmpty() const;

            Product& operator=(const Product& );
            bool operator==(const char* );
            int operator+=(int );
            int operator-=(int );


    };
    double operator+=(double& , const Product& );
    std::ostream& operator<<(std::ostream& os, const Product& );
    std::istream& operator>>(std::istream& is, Product& );

}



#endif

Product.cpp

#include <iostream>
#include <cstring>
#include "Product.h"

namespace sict {

    Product::Product() {
        sku_[0] = '\0';
        name_[0] = '\0';
        price_ = 0;
        quantity_ = 0;
        qtyNeeded_ = 0;

    }

    Product::Product(const char* sku, const char* name1, bool taxed1, double price1, int qtyNeeded1) {
        strncpy(sku_, sku, MAX_SKU_LEN);
        name(name1);
        quantity_ = 0;
        taxed(taxed1);
        price(price1);
        qtyNeeded(qtyNeeded1);

    }
    double Product::cost() const {
        if (taxed_ == true) {
            return (price_ * TAX) + price_;
        }
        else
            return price_;

    }

    bool Product::isEmpty() const{
        if (sku_ == nullptr && name_ == nullptr && quantity_ == 0  && price_ == 0 && qtyNeeded_ == 0) {
            return true;
        }
        else
            return false;
    }
    Product::Product(Product& ex) {
        sku(ex.sku_);
        price(ex.price_);
        name(ex.name_);
        taxed(ex.taxed_);
        quantity(ex.quantity_);
        qtyNeeded(ex.qtyNeeded_);

    }

    Product& Product::operator=(const Product& g) {

            sku(g.sku_);
            price(g.price_);
            name(g.name_);
            taxed(g.taxed_);
            quantity(g.quantity_);
            qtyNeeded(g.qtyNeeded_);

        return *this;
    }

    Product::~Product() {

            delete [] name_;

    }

    void Product::name(const char* name) {

        name_ = new char [strlen(name) + 1];
        strcpy(name_, name);

    }
    bool Product::operator==(const char* right) {
        if (sku_ == right) {
            return true;
        }
        else
            return false;
    }

    int Product::operator+=(int g) {
        quantity_ = quantity_ + g;
        return quantity_;
    }
    int Product::operator-=(int g) {
        quantity_ = quantity_ - g;
        return quantity_;
    }

    double operator+=(double& p, const Product& right) {
        p = p + (right.cost() * right.quantity());
        return p;
    }

    std::ostream& operator<<(std::ostream& os, const Product& g) {
        return g.write(os, true);

    }

    std::istream& operator>>(std::istream& is, Product& g) {
        return g.read(is);
    }



}

The General.h file referenced in the header is just a list of constant values such as the "TAX" and "MAX_SKU_LEN" values. The Streamable header contains pure virtual functions. I will list it here in case it is needed.

Streamable.h

#ifndef SICT__Streamable_H_
#define SICT__Streamable_H_
#include <iostream>
#include <fstream>
#include "Product.h"
namespace sict {
    class Streamable {
    public:

        virtual std::fstream& store(std::fstream& file, bool addNewLine = true)const = 0;
        virtual  std::fstream& load(std::fstream& file) = 0;
        virtual std::ostream& write(std::ostream& os, bool linear)const = 0;
        virtual  std::istream& read(std::istream& is) = 0;
    };
}
#endif

Thank you very much in advance.

Diggy
  • 3
  • 1
  • `name_[0] = '\0'` writing to a pointer that points nowhere? That's a paddlin'. You probably wanted `name_ = nullptr`, but you should be using an [initializer list](http://en.cppreference.com/w/cpp/language/initializer_list) Also it's 2016, please use `std::string`. – user657267 Mar 24 '16 at 00:20
  • @user657267 I would assume that `name_ = nullptr` would be better suited? – Diggy Mar 24 '16 at 00:24
  • It's not about suitability, `name_[0] = '\0'` is undefined behavior, `name_` doesn't point to anything at this point in time. Also your `name` function will result a memory leak if called more than once. – user657267 Mar 24 '16 at 00:27
  • 0xCC means you've read [uninitialized memory](https://stackoverflow.com/q/370195/995714) – phuclv Oct 17 '17 at 04:33

1 Answers1

0
Product::Product() {
    sku_[0] = '\0';
    name_[0] = '\0';    // <---- writing via unitialized pointer
    price_ = 0;
    quantity_ = 0;
    qtyNeeded_ = 0;

}

There's one possible source of your problems. You have defined a char pointer (a dynamic array or a C-string, that is) name_ in your class but you never allocate any memory for it in your constructor, before attempting to record a value via the pointer. Naturally, you get a write access violation.

Before assigning the value to char at index [0] you need to first allocate space for at least one element in your string, e.g. by doing name_ = new char [1]. Alternatively, you may choose to initialize the pointer itself to NULL (or nullptr) and use that to indicate that name_ has not yet been set.

TerraPass
  • 1,562
  • 11
  • 21