|
I'm using a parent class that holds pointers to child classes (parent-child is the application's terminology, not indicating heirarchy in c++).
The parent class has an array of pointers to children named "children"
To save space (and I need all I can get), I want to dynamically allocate this array. I have been using malloc/realloc with success in the past, but recently it's been reporting heap corruption:
"Heap block at 01720DD8 modified at 01720DE4 past requested size of 4"
before stopping at this line in memcpy_s.c:
"memcpy(dst, src, count);"
The realloc command in the code that is initiating the problem is indicated below. This array is initially malloc'd in the constructor of the class with a size of one child pointer.
bool parent::addchild(child *childToAdd){
//////////////////////////////
// Add child to children
//////////////////////////////
numchildren++;
children = (child**)realloc(children,(numchildren * sizeof(child*))); //<--Error occurs here
children[(numchildren-1)] = childToAdd;
return TRUE;
}
Thanks for any help
|
|
|
|
|
Slightly different error in Debug (original post was for Release):
Heap corruption:
"Heap block at 01F13EA0 modified at 01F13ED0 past requested size of 28"
Stops at the end brace of this function in mlock.c:
void __cdecl _unlock (
int locknum
)
{
/*
* leave the critical section.
*/
LeaveCriticalSection( _locktable[locknum].lock );
}
|
|
|
|
|
Read your error, the answer is there.
nadiric wrote: "Heap block at 01F13EA0 modified at 01F13ED0 past requested size of 28"
You requested a block of memory of size 28 bytes, it was given to you at address 01F13EA0, but you tried writing to it at address 01F13ED0 which is over the 28 byte limit. Basicly you are writing past the end of the array somewhere in your code.
|
|
|
|
|
my code effectively stops at the realloc indicated, it never makes it past this line...?
|
|
|
|
|
Run your code in the debugger, open the call stack window, and watch. When your code calls that function, there will be something like _invalid_pointer shown in the window. realloc() will check the memory for problems before doing what it should. Somewhere before calling the function, you have written past the end of the array. Just step through your code and look out for the address in the error message, thats when you will find your problem.
|
|
|
|
|
nadiric wrote: children = (child**)realloc(children,(numchildren * sizeof(child*))); //<--Error occurs here
So you only allocate memory for an array of child* pointers (which is 4 bytes on 32-bit Windows), not an array of children?
Best,
Jun
|
|
|
|
|
the array "children" holds pointers to "child" objects. Maybe the below will clarify.
child **children; //declaration in parent class
children = (child**)malloc(sizeof(child*)); //done in parent constructor
parent *parent1 = new parent;
child *child1 = new child; //creating a child somewhere in code
parent1.addchild(child1); //adding the child to a parent (the code in question)
|
|
|
|
|
Actually, this is something... Since you use the heap, why not just save child objects (instead of child* pointers). Theoretically it's OK, but it could cause implications to the memcpy() call, if the memory size not calculated correctly.
Best,
Jun
|
|
|
|
|
nadiric wrote: child *child1 = new child; //creating a child somewhere in code
parent1.addchild(child1); //adding the child to a parent (the code in question)
You may have issues here as well. new and malloc/calloc/realloc use different heaps. You are using new to allocate your objects and realloc to allocate your pointers. Mixing heaps like this can cause some interesting and hard to debug issues.
As a side note, you would probably get better performance by using a deque or a vector (with a pre-allocated buffer). Since each time you are adding a child, you are basically forcing a new memory allocation (actually 2, since you had to allocate the child object and then a pointer to it). You might find it easier, and more efficient to do something like the following:
class Child
{
public:
Child() : m_Data(0)
{
}
private:
int m_Data;
};
class Parent
{
public:
Parent()
{
}
void addChild(Child* pChild)
{
m_Children.push_back(pChild);
}
private:
std::deque<Child*> m_Children;
};
const unsigned long DEFAULT_SIZE = 100;
class Parent
{
public:
Parent()
{
m_Children.reserve(DEFAULT_SIZE);
}
void addChild(Child* pChild)
{
m_Children.push_back(pChild);
}
private:
std::vector<Child*> m_Children;
};
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
When you get heap corruption the actual cause need not be near where the problem manifests itself; often there is no obvious connection. He's what I'd try first:
- If you haven't already got it, down and install WinDBG[^]. This is an absolute essential and every C/C++ developer should have the latest version installed at all times.
- Select "Start->All Programs->Debugging Tools for Windows->Global Flags".
- Select the "Image File" tab.
- Type the name your application in the "Image: (TAB to refresh)" edit box then press TAB. The name should be the whole file name and extension but not the full path.
- Tick "Enable page heap", "Enable heap tail checking", "Enable heap free checking", "Enable heap parameter checking", "Enable heap validation on call" & "Create user mode stack trace database".
- Press "OK".
Now run your application. It will run many, many times slower then normal and consume huge amounts of memory but most heap errors will cause a break point to be generated as soon as the heap error occurs. If you use WinDBG as your debugger you can also get access to stack traces for each allocation. For example for a double free you can get a stack trace to the first free and a break point is generated for the second. It's good to have a machine with the fastest possible CPU and as much RAM as you can afford for debugging processes with the page heap.
After you've finished you'll want to turn the page heap off again for your process. Follow the steps above but uncheck all the tick boxes.
Steve
|
|
|
|
|
Lets say I have a class with quite a few public members, each time one of these functions is called I need to check a variable (by calling another function) before I can allow the code to proceed. Obviously I could insert the function call into each public function, but is there an alternative? What I'm worried about is somebody subclassing and forgetting to add the call into their extended function.
|
|
|
|
|
Private functions
A cynic is a man who, when he smells flowers, looks around for a coffin. -H.L. Mencken
|
|
|
|
|
hey thats a great idea, I will declare all of the class functions as private, that will stop those hackers from subclassing my class. One small drawback though, it won't work.
|
|
|
|
|
waldermort wrote: hey thats a great idea, I will declare all of the class functions as private, that will stop those hackers from subclassing my class. One small drawback though, it won't work.
JWood's answer was too short. He probably meant something like:
class Base {
public:
void doSomething() {
checkVar();
doSomethingImp();
}
private:
virtual void doSomethingImp() {
}
};
class Derived : public Base {
public:
private:
virtual void doSomethingImp() {
}
}
-- modified at 17:43 Thursday 7th September, 2006
see also: http://www.gotw.ca/publications/mill18.htm[^]
|
|
|
|
|
This probably isn't what wanted either. Just in case, if you coded in managed C++, you could use "sealed" modifier to a public function which you don't want to be derived from.
Best,
Jun
|
|
|
|
|
Are these public members variables or functions?
If these are functions, you can use something like the Pimpl-Idiom to hide the implementation a bit, so that if they subclass it, they won't have access to the "meat" of the object. For example:
class _MyClass;
class MyClass
{
public:
MyClass();
~MyClass();
void someFunc();
private:
_MyClass* m_pImpl;
};
class _MyClass
{
public:
_MyClass()
{
}
void someFunc()
{
}
};
MyClass::MyClass() : m_pImpl(new _MyClass)
{
}
MyClass::~MyClass()
{
delete m_pImpl;
}
void MyClass::someFunc()
{
m_pImpl->someFunc();
}
That way, deriving from MyClass would allow them to call the MyClass public/protected methods, but have no access to the actual data and can't circumvent (at least not easily) any requirements you are trying to place on the class.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
That's an excellent idea, I must remember this method. But in my current instance, I have simply added the function call to each function. If anybody does decide to override the methods, they are just going to have to read the docs.
|
|
|
|
|
Hello all,
can somenone explain to me the mean of
preprocessor directive: #pragma pack( pop, packing ) ?
Moreover can you tell me what the header pshpack1.h helps for?
thanx a lot
|
|
|
|
|
Did you see here?
"Talent without discipline is like an octopus on roller skates. There's plenty of movement, but you never know if it's going to be forward, backwards, or sideways." - H. Jackson Brown, Jr.
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
it pops packing directives off the stak until it finds one that matches the value of 'packing'. the MSDN's page on 'pragma pack' might help.
|
|
|
|
|
|
Hello,
I'm working to define a toolbar. I would like to modify the handle.
I have drawn a picture, put it inside the toolbar as handle but I could manage the picture as a handle. I Used a CStatic and then loaded a Bitmap into it.
Does somebody know how to get the picture ID to after allocate it as handle ?
titi
titi
|
|
|
|
|
I surprised myself, just coded the whole project in an ANSI environment, switched to unicode and only found 3 errors. Anyway, I have a _tprintf() call, which is returning -1. GetLastError() is not being set either, so I haven't a clue why it's not working.
TCHAR tmp[5];
if (i < 10)
_tprintf(tmp,_T("_00%d"),i);
else if (i < 100)
_tprintf(tmp,_T("_0%d"),i);
else
_tprintf(tmp,_T("_%d"),i);
_tcscat(newNames[i],tmp);
It works fine in an ANSI build.
|
|
|
|
|
First of all, have you tried doing this instead:
_tprintf(tmp, _T("_%03d"), i);
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week
Zac
|
|
|
|
|
yes,
TCHAR tmp[10];
memset(tmp,0,10);
if (i < 10)
_tprintf(tmp,_T("_%03d"),i);
Adding the memset has stopped it from returning -1, now returns 0. I have also tried removing all formating, but with no effect.
wprintf(tmp,L"Hello");
It just doesn't want to work
|
|
|
|