I have seen this answer (Advantages of using std::make_unique over new operator) where it states:
Don't use make_unique if you need a custom deleter or are adopting a raw pointer from elsewhere.
This is is my code:
void CAutomaticBackupSettingsPage::GetLastBackupDate(COleDateTime& rBackupDate)
{
DATE* pDatTime = nullptr;
UINT uSize;
theApp.GetProfileBinary(_T("Options"), _T("BackupLastBackupDate"), pointer_cast<LPBYTE*>(&pDatTime), &uSize);
if (uSize == sizeof(DATE))
rBackupDate = *pDatTime;
else
rBackupDate = COleDateTime::GetCurrentTime();
delete[] pDatTime;
pDatTime = nullptr;
}
Code analysis gives me two warnings:
and
The latter warning suggests I use std::make_unique but since my pointer data is returned from the GetProfileBinary call, and given the statement in the related question, does that mean I should not use std::make_unique? I admit it is something I have not done before.
The useage of GetProfileBinary clearly states:
GetProfileBinary allocates a buffer and returns its address in *ppData. The caller is responsible for freeing the buffer using delete[].
pDateTime is supposed to be nullptr, and GetProfileBinary handles the allocation. Code Analysis mistakenly thinks you forgot the allocation.
It does need to check for success before calling delete[]. We can't use delete[]pDatTime because pDatTime is not an array. But GetProfileBinary allocates using new BYTE[size], so we need to cast back to BYTE.
You can also add a NULL check before reading pDatTime, that might make Code Analysis happy.
if (pDatTime && uSize == sizeof(DATE))
rBackupDate = *pDatTime;
else
rBackupDate = COleDateTime::GetCurrentTime();
if(pDatTime) delete[](BYTE*)pDatTime;
You can use std::unique_ptr<BYTE[]> cleanup((BYTE*)pDatTime) for deletion, but this has to be after GetProfileBinary is called.
Example:
DATE* pDatTime = nullptr;
GetProfileBinary(_T("Options"), _T("BackupLastBackupDate"), (LPBYTE*)(&pDatTime), &uSize);
std::unique_ptr<BYTE[]> cleanup((BYTE*)pDatTime); //automatic delete
if (pDatTime && uSize == sizeof(DATE))
rBackupDate = *pDatTime;
else
rBackupDate = COleDateTime::GetCurrentTime();
//pDatTime = NULL; <- Error when used with unique_ptr
...
//pDatTime is deleted later, when `cleanup` goes out of scope
I have a DLL that is developed in VS 2019 environment.
It has following Interface.
GetValue(char* charPtr);
{
strcpy_s((char*)charPtr, sizeof(strSrc), strSrc.c_str());
}
Interface declaration in DLL
extern "C" __declspec(dllexport) GetValue(char* node);
I uses the above Interface in one of the console exe created in VS2008 Environment as follows.
char* charPtr = new char[size + 1];
getValue(charPtr);
delete [] charPtr;
I am getting the proper value in charPtr after invoking GetValue in the EXE, but when I try to delete charPtr, it is throwing an exception.
Console error string - "This may be due to a corruption of the heap, which indicates a bug in XXX.exe or any of the DLLs it has loaded"
As seen above, I have allocated and de-allocated the memory in EXE itself, still I am running into this error.
If I comment out just the getValue, delete work just fine.
Learnt to know that these issues are expected if binaries are created in different environment as is the case here. But tried the solutions mentioned in all of those threads, but to no avail.
What is wrong in the above code/approach?
Well Even if I invoke an interface of DLL without any parameters also causing issues. Now it is throwing below error
Run-time Check Failure #2 - Stack around the variable 'oss_' was corrupted.
In GetValue() you are passing the size of the string object instead of the actual size. Since your interface only provides a pointer without any size, the DLL function can not even know how much memory it can use, so this is already a bad decision.
Your interface should rather be:
extern "C" __declspec(dllexport) size_t GetValue(char* node, size_t nodeLen);
size_t GetValue(char* charPtr, size_t bufferlen);
{
// Return the required size but don't copy as memory is to small
if (bufferlen < strSrc.length()+1)
return strSrc.length()+1;
strcpy_s((char*)charPtr, bufferlen, strSrc.c_str());
return strSrc.length();
}
And then you can use it like this:
char* charPtr = new char[size + 1];
size_t len = size+1;
if((len = GetValue(charPtr, len)) > size+1)
{
// Error, memory to small;
delete [] charPtr;
charPtr = new char[len];
GetValue(charPtr, len);
}
delete [] charPtr;
or
size_t len = 0;
// Ask for required size
len = GetValue(charPtr, len);
char* charPtr = new char[len];
GetValue(charPtr, len);
delete [] charPtr;
I am implementing a stack and I would like to push and pop string data. can I not just set
string name = originalString ???
here is what I have for push:
void push(StackNode** top_ref, int nAttack, int nDefense, string nName, string nType) {
StackNode* stackNode = (StackNode*)malloc(sizeof(StackNode));
stackNode->attack = nAttack;
stackNode->defense = nDefense;
stackNode->name = nName; //not working
stackNode->type = nType; //not working
stackNode->next = NULL;
stackNode->next = *top_ref;
*top_ref = stackNode;
}
where stackNode->name
and stackNode->type is already defind as a string
I keep getting: "Error reading characters of string."
The issue is malloc doesn't play well with objects. See Does malloc create a new instance of the class or not?
malloc allocates enough space to hold a StackNode, but doesn't call the constructor on it. Nor does it create the underlying member objects, your strings included. To do so, you need to do like described in this answer:
A* a = (A*)malloc(sizeof(A));
new (a) A();
a->~A();
free(a);
But at this point, you really should just be using new anyway. There's very little reason to use new in C++ (there's a time and a place, but minimize it). There's even fewer times when it's right to call malloc.
Do
StackNode* stackNode = new StackNode;
which will call the constructor appropriately. Remember to call delete on the memory when you're done with it!
I'm working on a program for a lab, and I need some help with the memory management. I'm new to C++ as a whole, and while I have experience in other languages, dynamic memory management is confusing me. Also, because this is for a lab, I can't use std::vector or smart pointers, just arrays and pointers.
First, there's a "Vehicle" class, with some attributes describing it (such as make, model, etc). Next, there's a "Showroom" class, which contains an array of Vehicles:
Vehicle * m_vehicles;
And later, in the constructor:
m_vehicles = new Vehicle[m_maxCapacity];
Next there's a "Dealership" class, which has an array of Showrooms:
Showroom * m_showrooms;
...
m_showrooms = new Showroom[m_maxCapacity];
My main() method creates some vehicles, adds those to showrooms, and then adds those to a dealership. Everything works without issue until the program ends. When the program finishes and the objects are deleted, some problems come up. As the dealership was created last, it is deleted first. It's destructor calls delete[] m_showrooms; , and the destructor in the Showroom class calls delete[] m_vehicles;. So, I expect that when the program ends, the OS deletes the dealership object, which removes the showroom objects, which in turn remove the vehicle objects.
However, it doesn't work properly. The lab requires that we use a helper that has been provided which marks memory leaks as errors. When
my main() creates a showroom, adds vehicles to it, creates a dealership, and then adds the showroom to the dealership, when the program ends the memory leak detector gives an error, saying:
delete[] error: pointer was not allocated!
I get this error once for every showroom I add to the dealership. Also, there's another bizarre error: I get a segfault when the program ends if the dealership contains any two showrooms which have the same capacity.
If I say "screw it" and remove all of the delete[]'s from the destructors, the program runs without a segfault, but the memory leak program detects the leak and prevents me from moving on.
What am I doing wrong? Do I have some sort of fundamental misunderstanding of dynamic memory in C++? I read that every new[] should match with a delete[], and that's what I have. I've already asked my TA about this, and she didn't have any idea about how to solve it.
EDIT: Here's some relevant code:
main.cpp:
//array of vehicles to store
Vehicle vehicles[] =
{
Vehicle("Ford", "Mustang", 1973, 9500, 113000),
Vehicle("Mazda", "CX-5", 2017, 24150, 5900),
Vehicle("Dodge", "Charger", 2016, 18955, 9018),
Vehicle("Telsa", "Model S", 2018, 74500, 31),
Vehicle("Toyota", "Prius", 2015, 17819, 22987),
Vehicle("Nissan", "Leaf", 2016, 12999, 16889),
Vehicle("Chevrolet", "Volt", 2015, 16994, 12558),
};
// Showrooms to store the vehicles
Showroom showroom("Primary Showroom",2);
showroom.AddVehicle(&vehicles[0]);
showroom.AddVehicle(&vehicles[1]);
//showroom.AddVehicle(&vehicles[2]);
Showroom secondary("Storeroom 2",4);
secondary.AddVehicle(&vehicles[3]);
secondary.AddVehicle(&vehicles[4]);
secondary.AddVehicle(&vehicles[5]);
secondary.AddVehicle(&vehicles[6]);
// A "parent" object to store the Showrooms
Dealership dealership("Dealership",2);
dealership.AddShowroom(&showroom);
dealership.AddShowroom(&secondary);
//displays the showrooms and their contents
dealership.ShowInventory();
Relevant functions from Vehicle.cpp:
Vehicle::Vehicle(std::string mk, std::string md, int yr, int pr, int ml) {
make = mk;
model = md;
year = yr;
price = pr;
miles = ml;
}
Vehicle::~Vehicle() {}
Vehicle::Vehicle(const Vehicle &veh) {
//year = new int;
make = veh.make;
model = veh.model;
year = veh.year;
price = veh.price;
miles = veh.miles;
}
Vehicle& Vehicle::operator=(const Vehicle &veh) {
make = veh.make;
model = veh.model;
year = veh.year;
price = veh.price;
miles = veh.miles;
return *this;
}
Vehicle::Vehicle() {}
From Showroom.cpp:
//copy constructor
Showroom::Showroom(const Showroom &s)
{
m_name = s.m_name;
m_maxCapacity =s.m_maxCapacity;
m_currentNumberOfVehicles = s.m_currentNumberOfVehicles;
m_vehicles = new Vehicle[m_maxCapacity];
for (int i = 0; i< s.m_currentNumberOfVehicles;i++)
{
m_vehicles[i] = *new Vehicle(s.m_vehicles[i]);
}
}
//normal constructor
Showroom::Showroom(std::string name, unsigned int maxCapacity) {
m_name = name;
m_maxCapacity = maxCapacity;
m_vehicles = new Vehicle[m_maxCapacity];
m_currentNumberOfVehicles = 0;
}
Showroom::~Showroom() {
delete[] m_vehicles;
}
Showroom::Showroom(){}
From Dealership.cpp:
//copy constructor
Dealership::Dealership(const Dealership &d)
{
m_name = d.m_name;
m_maxCapacity =d.m_maxCapacity;
m_currentNumberOfShowrooms = d.m_currentNumberOfShowrooms;
m_showrooms = new Showroom[m_maxCapacity];
for (int i = 0; i< d.m_currentNumberOfShowrooms;i++)
{
m_showrooms[i] = *new Showroom(d.m_showrooms[i]);
}
}
//normal constructor
Dealership::Dealership(std::string name, unsigned int capacity) {
m_name = name;
m_maxCapacity = capacity;
m_currentNumberOfShowrooms = 0;
m_showrooms = new Showroom[m_maxCapacity];
}
Dealership::~Dealership() {
//std::cout<<"Deleting dealership " <<m_name << std::endl;
delete[] m_showrooms;
//m_showrooms = 0;
}
EDIT 2: Here is the smallest amount of code in main() that gives and error saying that I tried to deallocate a pointer that wasn't allocated:
Showroom sh("Name", 0);
Dealership dealer("dealer", 1);
dealer.AddShowroom(&sh);
Here's the smallest amount of code that segfaults:
Showroom sh("Name", 0);
Showroom sh2("Showroom 2",0);
Dealership dealer("dealer", 2);
dealer.AddShowroom(&sh);
dealer.AddShowroom(&sh2);
And here's AddShowroom(), for reference:
void Dealership::AddShowroom(const Showroom *showroom) {
m_showrooms[m_currentNumberOfShowrooms] = *showroom;
m_currentNumberOfShowrooms++;
}
There are many issues with your code, and they could all lead to segfaults in one way or another.
To add to what #ShadowRanger has pointed out, sh and sh2 are not dynamically allocated, and the dealer is keeping a reference to them. These two objects get destroyed automatically when they go out of scope. So when that happens dealer will be operating on objects that no longer exists and a segmentation fault will ensue.
Another cause of segmentation fault I see is due to m_showrooms not getting resized when its capacity is exceeded. The line m_showrooms = new Showroom[m_maxCapacity]; allocates m_maxCapacity number of slots for Showroom pointers. As you call AddShowroom, you need to check if this capacity is going to be exceeded. If so, you need to allocated a larger array, move the objects over, then destroy the old array (and not the objects it houses).
From what I can tell, you seem to be unfamiliar with the idea of how memory is handled in C++. I suggest spending time to figure this out because it will save you a lot of headaches down the road.
These lines are guaranteed memory leaks:
m_vehicles[i] = *new Vehicle(s.m_vehicles[i]);
and:
m_showrooms[i] = *new Showroom(d.m_showrooms[i]);
That's dynamically allocating, dereferencing, and using the dereferenced value to copy assign into the array. But the pointer to the original dynamically allocated value is immediately lost; you're leaking memory the instant you allocate it.
You really wanted:
m_vehicles[i] = Vehicle(s.m_vehicles[i]);
and:
m_showrooms[i] = Showroom(d.m_showrooms[i]);
Your segfaulting code is faulting for obvious reasons:
Dealership dealer("dealer", 1);
claims at most one showroom will be allocated, then you call AddShowroom twice, and write off the end of the allocated memory (likely corrupting the heap, and who knows what else).
I can't say for sure why it's complaining about unallocated pointers, but you've got so many leaks and out-of-bounds errors lying around, with so much of your code omitted, that it's hard to say for sure I haven't missed something, vs. the code with the error isn't there to check. The sort of error you're experiencing could be caused by heap corruption (which you're definitely causing at various times) or by double delete[]ing a pointer. No obvious code is doing this, but you haven't provided a MCVE (what you've provided is neither minimal nor complete), so it could be hiding.
I'm writing my first opencv code(and first C++ code actually), and met with a strange munmap_chunk(): invalid pointer error when I try to use cv::Ptr. I see in other posts that this usually results from freeing a already freed area, but I think I didn't.
The following simple testing function will generate that error.
void testing(void) {
int i=2;
Ptr< Mat > pointer=new Mat[i];
}
From the debugger, it seems that the destructor triggers the error when the function returns.I couldn't figure out why since basically I did nothing with the Ptr. So why this is happening and what's the correct usage?
Thanks in advance.
In C++ there is a significant difference between memory allocated with new and memory allocated with new [].
int* p = new int;
delete p;
p = new int[8];
delete p; // error/crash
delete [] p; // correct
The Ptr class is an RAII container for managing ownership of pointers. When you assign to it, it takes ownership of that allocation, meaning it will delete it when the Ptr goes out of scope (in this case at the end of the function).
It uses delete by default hence your crash, and the documentation suggests you will need to use the constructor that lets you specify you own deleter:
// see http://docs.opencv.org/master/d0/de7/structcv_1_1Ptr.html
void array_deleter(Mat* m)
{
delete [] m;
}
Prt<Mat> ptr(new Mat[i], array_deleter);