0

My program calls a function called _free_base but I don't have it on any part of my program. And when I debugged it, I found out that the error happened in the following snippet but I couldn't isolate the exact position :

HWND CreateComboBox(HWND hwnd, vector<Product> products, int charWidth, int charHeight)
{
  HWND result = CreateWindow(WC_COMBOBOX, TEXT(""),
      CBS_DROPDOWN | CBS_HASSTRINGS | WS_VISIBLE | WS_OVERLAPPED | WS_CHILD,
    102 + 2 * charWidth, (products.size() + 1) * charHeight, 
    100, 100, hwnd, NULL,
    (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), NULL);

  for (unsigned int iii = 0; iii < products.size(); iii++)
  {
    ComboBox_AddString(result, products[iii].name);
  }

  ComboBox_SetCurSel(result, 0);

  return result;
}

That's the part of my program where the error happened. The VS call stack stated that the next function to be called is the return result part. Which means that it happened during ComboBox_SetCurSel right? But when I erased that part, the next function to be called is still return result. That's why I couldn't isolate the exact error position. On the call stack, the function above this one is this Microsoft file:

free.c

    void __cdecl _free_base (void * pBlock)
    {

      int retval = 0;


      if (pBlock == NULL)
          return;

      RTCCALLBACK(_RTC_Free_hook, (pBlock, 0));

      retval = HeapFree(_crtheap, 0, pBlock);
      if (retval == 0)
      {
          errno = _get_errno_from_oserr(GetLastError());
      }  
    }

And the error is at the retval = HeapFree...

Finally, the Output window in VS posted this Unhandled exception at 0x77133873 (ntdll.dll) in Inventory Program.exe: 0xC0000374: A heap has been corrupted (parameters: 0x7714CDD8).

I'm new here, so if you need any more information please just ask in the comments and don't rate down my question. Thanks.

Oh yes here's the Call Stack :

ntdll.dll!_RtlReportCriticalFailure@8()

ntdll.dll!_RtlpReportHeapFailure@4()    Unknown

ntdll.dll!_RtlpLogHeapFailure@24()  Unknown

ntdll.dll!_RtlFreeHeap@12() Unknown

kernel32.dll!_HeapFree@12() Unknown

>msvcr120.dll!free(void * pBlock) Line 51

Inventory Program.exe!CreateComboBox(HWND__ * hwnd, std::vector<Product,std::allocator<Product> > products, int charWidth, int charHeight) Line 74

Inventory Program.exe!WndProc(HWND__ * hwnd, unsigned int message,  unsigned int wParam, long lParam) Line 139  C++

[External Code] 

Inventory Program.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int iCmdShow) Line 48 C++

[External Code] 

EDIT : Here's my Product class

product.h

#ifndef STOCK_H
#define STOCK_H
#include <vector>
#include <iostream>
#include <tchar.h>

using namespace std;

class Product
{
 public:
 TCHAR* name;
 double price;
 int stock;

 Product(string, double, int);

 ~Product();

 void sell(int sold);
 void stockup(int stocked);

};

void initProductList(vector<Product> &p_list);

void saveProductData(vector<Product> &p_list);

#endif

product.cpp

#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include "product.h"

using namespace std;

Product::Product(string a, double b, int c)
{
    const char* cStringForm = a.c_str();

    name = new TCHAR[strlen(cStringForm) + 1];

    name[a.size()] = 0;

    copy(a.begin(), a.end(), name);

    price = b;
    stock = c;
}

Product::~Product()
{
    delete[] name;
}

void Product::sell(int sold)
{
    stock -= sold;
}

void Product::stockup(int stocked)
{
    stock += stocked;
}

void initProductList(vector<Product> &p_list)
{
    //Fills the p_list vector with Product objects

    p_list.reserve(50);

    //There is no file which contains the amount of products
    //It is placed in the first line of the product_name_file
    ifstream product_name_file("C:\\Users\\Jonathan\\My Programs\\Projects\\Inventory Program\\product_names.txt");
    ifstream product_price_file("C:\\Users\\Jonathan\\My Programs\\Projects\\Inventory Program\\product_prices.txt");
    ifstream product_stock_file("C:\\Users\\Jonathan\\My Programs\\Projects\\Inventory Program\\product_stocks.txt");
    int product_quantity(0);
    product_name_file >> product_quantity;

    for (int iii = 0; iii < product_quantity; iii++)
    {
        string name;
        double price;
        int stock;

        product_name_file >> name;
        product_price_file >> price;
        product_stock_file >> stock;

        Product a(name, price, stock);

        p_list.push_back(a);
    }

    product_name_file.close();
    product_price_file.close();
    product_stock_file.close();

}

void saveProductData(vector<Product> &p_list)
{
    ofstream productName("C:\\Users\\Jonathan\\My Programs\\Projects\\Inventory Program\\product_names.txt", 
    ofstream::out | ofstream::trunc);
    ofstream productPrice("C:\\Users\\Jonathan\\My Programs\\Projects\\Inventory Program\\product_prices.txt",
    ofstream::out | ofstream::trunc);
    ofstream productStock("C:\\Users\\Jonathan\\My Programs\\Projects\\Inventory Program\\product_stocks.txt",
    ofstream::out | ofstream::trunc);

    productName << p_list.size() << "\n";

    for (unsigned int iii = 0; iii < p_list.size(); iii++)
    {
        productName << p_list[iii].name << "\n";
        productName.flush();
        productPrice << p_list[iii].price << "\n";
        productPrice.flush();
        productStock << p_list[iii].stock << "\n";
        productStock.flush();
    }
    productName.close();
    productPrice.close();
    productStock.close();
}
J.Alvaro.T
  • 138
  • 2
  • 2
  • 12
  • 1
    The bug is in your `Product` implementation. If you want to postpone the bug to a later point, pass a `const vector&` to your `CreateComboBox` method. – IInspectable Jul 11 '15 at 16:20
  • 1
    Your program is corrupting memory. Try running with application verifier or other memory checking debugging tools like valgrind. – Raymond Chen Jul 11 '15 at 16:40
  • @IInspectable The implementation as in the constructor?. – J.Alvaro.T Jul 12 '15 at 02:09
  • @IInspectable or is it because of the `TCHAR* name` ? Because I used `std::string` for my `name` variable type for my command line version of the program. But, I had to change it to TCHAR* because the functions provided by WinAPI needs them. – J.Alvaro.T Jul 12 '15 at 02:18
  • You violated the [Rule of Three](https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)). When you `push_back` the products into the vector, the default copy constructor is used, which eventually leads to a double-free bug when the vector is destructed. – Raymond Chen Jul 12 '15 at 02:56
  • @RaymondChen I'll try to create the copy constructor. Btw, thanks for the link. Never heard of that before. So, whenever I pass an argument by value the copy constructor is called. So, the problem is because the pointer is freed twice? – J.Alvaro.T Jul 12 '15 at 03:04
  • @RaymondChen your suggestion works! Thanks! Now I just have to finish another heap block problem in this program. Now I know why people hate memory management – J.Alvaro.T Jul 12 '15 at 03:52
  • @RaymondChen Thank you sir! For this and helping me with your answer for another question! The one where the hwnd parameter in the message loop should be NULL. thanks! – J.Alvaro.T Jul 13 '15 at 04:39

0 Answers0