I got a problem with the following code, which I can't solve since hours...
I'm glad for any kind of advice.
The types are defined as follows:
typedef std::vector< cv::RotatedRect > ds_t;
typedef struct id_ {
std::string path;
std::string fileName;
} id_t;
typedef struct dd_ {
cv::RotatedRect bB;
} dd_t;
typedef std::pair<id_t, std::vector<dd_t> > ts_t;
typedef std::vector<ts_t> tss_t;
Then I try to fill the type with data:
tss_t samples
while (readdir(pDir) != NULL) {
ts_t sample;
sample.first.path = _path;
sample.first.fileName = _name;
ds_t detections;
getDetections(_path, detections); //this only filles the detecions byref
for(size_t i=0; i<detections.size(); i++) {
dd_t data;
data.bB = detections[i];
sample.second.push_back(data); //TODO FIXME
}
samples.push_back(sample);
}
cv::RotatedRect is a very basic class.
class RotatedRect{
public:
RotatedRect();
RotatedRect(const Point2f& _center, const Size2f& _size, float _angle);
void points(Point2f pts[]) const;
Point2f center;
Size2f size;
float angle;
};
bool getDetections(const std::string &imagePath, ds_t &detections)
{
//some processing
for(size_t i=0;i<5;i++)
detections.push_back(RotatedRect(cv::Point2f(110.,110.), cv::Size2f(10.,10.), 90.0f));
return true;
}
Hopefully I copied the whole code and I know, I don't need most of the typedefs...
I have already tried to reserve space sample.second.reserve(detections.size()), but this only postpones the error to samples.push_back.
The erroneous line is indicated by the FIXME, causing "terminate called after throwing an instance of 'std::bad_alloc'"
Thanks for any advice in advance.
std::bad_alloc generally means that you've run out of memory -- possibly because of a leak, or just because you've allocated too much. It can also (rarely) happen due to heap corruption (running off the end of an allocated array or dereferencing a pointer after it has been deleted) or other undefined behavior at some earlier point in the program.
How much memory is your program trying to use at one time? You can try using a leak detector like valgrind to see if there is stuff you should be cleaning up.
edit
The -1 to __builtin_new tells you a lot -- it tells you that someone is calling new with a bogus size. That would probably be a member of std::vector that tries to resize things (you can check the stack trace from valgrind or use a debugger to be sure), which indicates that the vector has been corrupted. Since sample.second is a local (on stack) variable, that tells you that a previous function you called (probably getDetections) overran an onstack buffer or array of some kind and clobbered sample.second. So take a careful look at what that function is doing -- the code you've commented out as //some processing. You can also try using a debugger to set a breakpoint just after sample is created and then set a watchpoint on the memory used by sample.second that is getting corrupted. Then continue the program and it should stop at the point that is clobbering sample.second
It may be helpful to read your compiler's header files to figure out how it implements std::vector -- there's probably a couple of size_t fields and a pointer field in there.
Related
I have a class with a member function mBoundingBox made up of the following struct
typedef struct
{
unsigned int xMin;
unsigned int yMin;
unsigned int xMax;
unsigned int yMax;
} boundingBox;
class CImgProc
{
public:
CImgProc(void);
virtual ~CImgProc(void);
...
boundingBox *mBoundingBox;
...
}
In code I allocate the member:
mBoundingBox = new boundingBox [mBlobCnt];
piddle around with it (don't assign any pointers to it, just using array indexing), then, when I exit I:
if (mBoundingBox != NULL) delete [] mBoundingBox;
and this is causing an error.
Any input?
Updated info. The error does occur at termination in the destructor. The message generated by VS is:
Windows has triggered a breakpoint in ProcImage.exe.
This may be due to a corruption of the heap, ...
This may also be due to the user pressing F12 while ProcImage.exe has focus.
The output window may have more diagnostic information.
I am setting the pointer to NULL in the constructor and then allocating (with new) when I need to. The pointer is valid, but apparently not on the heap (break lands in dbgheap.c).
Once I allocate the memory, I don't happen to do any pointer magic with it. In this case I am looping through an image and gather stats. Then I use the stats stored in this memory to draw back into my image, but, again, in a rather brute force manner, so nothing else makes use of this memory.
It is legal for me to use new to create an array of structs isn't it?
Doh!!! Sorry to waste ya'lls time. I dug back in and discovered that my creation and destruction are fine, but somewhere in the middle I set the value of mBoundingBox[X]. whatever where it turns out X is the dim of the array created.
Typical user error, just a surprising place for the bug to show up.
Most probably you are deleting your array twice. To manage it better use
delete[] mBoundingBox;
mBoundingBox = 0;
instead of
if (mBoundingBox != NULL) delete [] mBoundingBox;
or even better use a smart pointer.
first of all the following check is wrong
if (mBoundingBox != NULL) delete [] mBoundingBox;
new does not returns NULL when it fails to allocate memory, rather it throws an exception.
use nothrow version of "new" if you want to proceed like you are doing. In nothrow version new will return NULL instead of throwing an exception.
mBoundingBox = new (std::nothrow) boundingBox [mBlobCnt];
I have a std::vector that is causing some very strange seg faults
//A.h
class A{
private:
std::vector<float> data;
public:
void set(const std::vector<float>& data);
};
//A.cpp
void A::set(const vector<float>& data){
this->data.clear(); // crashes on this line
for(float f : data) this->data.push_back(f);
}
Under what possible circumstances could vector::clear() cause a seg fault? I initially had
void A::set(const vector<float>& data){
this->data = data;
}
and had the same problem. I switched to the above to debug.
This is on gcc 4.7.2, x86_64
IF it crashes precisely at the call to 'data.clear' (I mean, at exactly this line, not somewhere inside the clear), then be sure to check your this pointer at the faulting line.
If somehow your $this is null or trash-value due to accumulated effects of previous bugs, then this line might behave similarily.
On the (almost) other hand, if it actually crashes somewhere inside the clear and you just have cut the stacktrace to make the problem description more succint, then still it is possible to be the same cause.
You may check the 'this' pointer for NULL easily in the debugger. Also, detecting trashvalues is not hard: add some testfields to the A class, fill them in constructor with some predictable BUT NOT CONSTANT values, and when the app crashes, check if the this->mytestvalue is ok. If the $this is trashed, then the pointed test values will very often be almost random.
Likely this is due to stack/memory corruption occurring somewhere else. You should run your program with a memory checker, such as Valgrind using the memcheck tool to see what's going on.
Working on adjacency list --> directed weighted graph
One class looks like this, i.e. header:
class CGraph;
class CMap {
public:
//voided constructors and destructors
//functions one is:
void SetDirGraph(string commands);
private:
CGraph* m_myMap;
};
Second class:
class CNode {
public:
//voided constructor and desctructor
int m_distance, m_vert;
bool m_isKnown;
};
typedef struct edges {
int v2, weight;
} edge;
class CGraph {
public:
CGraph(int map_size);
~CGraph(void);
void AddMap(int v1, int v2, int weight);
void AddEndVert(int v2, int weight);
private:
list<edge> List;
int size;
public:
CNode* verts;
};
I'm reading vertices from a file, and that works. My problem is I am having trouble creating an adjacency list based on the code given. I'm trying to use pointers first that points to a list and it is not working correctly. I don't know how to create my pointers to the list without writing over them.
void CMap::SetDirGraph(string command) {
istringstream buffer(command)
char ch;
int num, vert1, vert2, weight; //specify vertices and weight and number of vertices
buffer>>ch; //throw away first character (not needed)
buffer>>num // size of vertices
while(!buffer.eof()) { // keep reading until end of line
buffer>>v1; // vertex start
buffer>>v2; // vertex end
buffer>>weight;
m_myMap = new CGraph(map_size); //initialize m_myMap.
m_myMap->verts->m_vert = v1; // mymap->verts->vert points to first edge
m_myMap->AddMap(v1, v2, weight); // create list?
m_myMap->AddEndVert(v2, weight); //create list? push v2 and weight on my list using my list.
}
}
I've tried several different ways and I keep confusing myself, any point in the right direction would be awesome.
EDIT:
I have more code too if needed to be produced, just publishing the main stuff.
What I mean by "not working" is that I am just writing over the previous vertex. I don't know if I should create an array using m_myMap (tried and still writes over and get a memory error as well). No compiler errors.
I don't know how to create my pointers to the list without writing over them.
Apart from your application, the answer to this question is the new operator, which I assume you are aware of, since you used it within your example code. Code like int * a = new int(42); allocates memory for an int on the heap and you are responsible for cleaning it up when it is not needed anymore. You thereby have full control over how long a variable will be available. In int x = 42; int * a = &x; on the other hand, x will automatically be cleaned up when it runs out of scope, and a will be a pointer to a memory block that has no meaningful data in it anymore. If you try to dereference it, you will encounter undefined behavior, and, if you are lucky, your program will blow up.
If you can use the C++11 standard, or a library that offers smart pointers, you should prefer those over managing the pointer yourself whenever possible. A smart pointer is an object that holds the allocated memory and frees it automatically when it is destructed. More specific information depends heavily on which sort of smart pointer you are using. The reason for using smart pointers is that doing the management yourself is tedious and error prone. If you do not delete your pointers you had allocated, your application will keep on allocating more memory until it blows up some day (depending on how often and how much memory you allocate); this is called leaking. If you call delete more than once, your program will bail out as well. Here is an example of C++11 shared_ptr in your application:
class CMap
{
private:
std::shared_ptr<CGraph> m_myMap;
// etc.
};
// in SetDirGraph
m_myMap.reset( // if the smart pointer has previously been managing
// memory, it will free it before allocating new
new CGraph(map_size) // allocate CGraph as before
);
Besides that, what hopefully answers your question, I have run into several potential problems concerning your code:
Definitely wrong:
In SetDirGraph you set m_myMap->verts->m_vert = v1. m_myMap->verts is a pointer. You have freshly created m_myMap and thus verts is not initialized, hence pointing at a random block of memory. You then try to dereference it by m_myMap->verts->m_vert = v1. This cannot work. You need to create verts first, i.e. verts = new CNode;.
typedef struct edges { /* etc */ } edge; is a C construct and there is no need for the typedef wrapper in C++. It does work and all, but it is really redundant and lots of those constructs just pollute the namespace you are working in.
Do you really need pointers in the first place? Your provided snippets do not hint at why you would need to use them. You will want to reduce usage of pointers to a minimum (or at least use smart pointers, see above)
UPDATE (SOLVED): All right, I'm a complete idiot! Turns out in the "do stuff with data" part in my main program I ended up incrementing the pointer, so the delete obviously wouldn't work! D'oh!
So I am compiling a shared library that has a function similar to this (super simplified view), and this library is also mine- so I know how data is allocated:
// inside library
void* getData(int size) { // with other parameters
UINT8* data = new UINT8[size]; // where typedef uint8_t UINT8; for gcc
// do a socket read, where data is the buffer
blockingRead (someSocket, data, propertySize);
return (void*) data;
}
It has to return a void pointer, as the data could be a struct (so one can just cast to the struct).
The problem is, I am using this pointer in my main program, and I want to delete it when I'm done. If I do this in my main program:
// inside main program
char* data = (char*) Library::getData(5);
// do stuff with data
delete[] data; // crashes with:
// *** glibc detected *** core: free(): invalid pointer: 0x00002aaab007bca4 ***
I thought maybe I should delete it in the shared library instead:
// inside library
void disposeData(void* data) { // call this from main program
delete[] (UINT8*) data; // cast it back to the original type of pointer
}
But I still get the same crash! Everything works fine and dandy if I don't delete, but I don't want unnecessary memory leaks all over my program.
I'm probably doing something dumb somewhere- please help me find the error in my ways!
EDIT: As pointed out in the comments, it seems that the above code works- I will have to see what specifically causes the errors in my code.
Have you tried using valgrind? Using valgrind will help you pinpoint a wide range of memory management errors, which are the likely cause of the problem. The error you are seeing looks either like heap corruption (as #nos says, probably in the do stuff part), or that you are not in fact freeing the same object you originally allocated.
If the library is providing you with allocated pointers, it should explain how to deallocate them. It may provide its own function for deallocation. Unless you have the source code to the library and can verify that it is using new[] to create the pointer, you can't be sure how it is allocating memory. Your crash is likely because your deallocator doesn't match its allocator.
How about using a more RAII based design such as smart pointers instead? Boost smart pointers are quite well designed.
I bet you're doing something like that, as you mention "casts":
#include <stdio.h>
class B { int x; };
class C { int y; };
class A : public B, public C { };
void* getData()
{
A* a = new A();
printf("%p\n", a);
C* c = a;
printf("%p\n", c);
return c;
}
void deleteData(void* x)
{
// delete (A*)x; // incorrect; causes crash
delete (A*)(C*)x; // correct
}
int main()
{
void* x = getData();
deleteData(x);
return 0;
}
Beware, the compiler may be translating what looks like an innocent cast into pointer arithmetic behind your back.
I have a class here that is defined like this:
struct USERFPOINT
{
POINTFLOAT UserPoint;
POINTFLOAT LeftHandle;
POINTFLOAT RightHandle;
bool isBezier;
};
struct SHAPEOUTLINE {
GLuint OutlineVBO;
int OutlineSize;
int OutlineWidth;
ARGBCOLORF OutlineColor;
};
struct SHAPECONTOUR{
std::vector<USERFPOINT> UserPoints;
std::vector<std::vector<GLdouble>> DrawingPoints;
SHAPEOUTLINE Outline;
};
struct SHAPEGRADIENT{
GLuint TextureId;
bool IsParent;
bool active;
int type;
std::vector<ARGBCOLORF> colors;
};
struct SHAPEDIMENSIONS {
POINTFLOAT Dimensions;
POINTFLOAT minima;
POINTFLOAT maxima;
};
class OGLSHAPE
{
private:
int WindingRule;
GLuint TextureCoordsVBOInt;
GLuint ObjectVBOInt;
UINT ObjectVBOCount;
UINT TextureCoordsVBOCount;
SHAPEGRADIENT Gradient;
SHAPEDIMENSIONS Dimensions;
void SetCubicBezier(USERFPOINT &a,USERFPOINT &b, int ¤tcontour);
void GenerateLinePoly(const std::vector<std::vector<GLdouble> > &input, int width);
public:
std::string Name;
ARGBCOLORF MainShapeColor;
std::vector<SHAPECONTOUR> Contour;
OGLSHAPE(void);
void UpdateShape();
void SetMainColor(float r, float g, float b, float a);
void SetOutlineColor( float r, float g, float b, float a,int contour );
void SetWindingRule(int rule);
void Render();
void Init();
void DeInit();
~OGLSHAPE(void);
};
Here is what I did as a test. I created a global std::vector<OGLSHAPE> test .
In the function I was using, I created
OGLSHAPE t.
I then pushed 50,000 copies of t into test.
I then instantly cleared test and used the swap trick to really deallocate it.
I noticed that all the memory was properly freed as I would expect.
I then did the same thing but before pushing t into test, I pushed a SHAPECONTOUR (which I had just created without modifying or adding anything into the contour) before pushing t into test.
This time after clearing test, 3 more megabytes had been allocated. I did it again allocating twice as many and now 6MB we remaining. The memory usage of the program peaked at 150MB and it went down to 12MB, but it should be at 8.5MB. Therefore, this must be classified as a memory leak, although I do not see how. There is nothing that I see that could do that. SHAPECONTOUR is merely a structure of vectors with a nested structure of vectors.
Why would this cause a leak, and how could I fix it?
Thanks
If you've deleted everything, there is no leak, by definition. I don't see any unwrapped pointers, ergo everything gets deleted. Therefore, you have no leaks.
Likely, the OS has simply decided to leave that memory available to your program, for whatever reason. (It hasn't "reclaimed" it.) Or maybe it needs to allocate in groups of4MB, and so going from 12MB to 8MB wouldn't leave enough required memory. Or...
You're cutting out other reasons entirely; you should use a real memory leak tool to find memory leaks.
When you allocate large chunks of memory, the CRT keeps some of it around for when you need to allocate again. You can't use Task Manager to indicate leaks.
If your class uses self-clearing members like vector, they do not leak memory.
How about explicitly clearing the vectors of SHAPECONTOUR in the destructor of OGLSHAPE? Rerun your test with this & check if you still have the observed leak.
How are you clearing that vectors? Try using in destructors something like this:
std::vector<SHAPECONTOUR>().swap(Contour);
And do the same with other vectors from your code(UserPoints, DrawingPoints, colors).
I would suggest to use a leak detection tool to find out if you really have a leak. For example for Windows dev you can use Visual Leak Detetor (VLD).
If you do indeed have a leak then it is probably not where you think it is.
Also you may just be wrong in that there is no leak at all. For example if you are looking just at the stats via something like task manager, this does not mean there is a leak in your program. The OS that runs your program is a separate beast than the programming language that you may have a leak inside of. I.e. the OS can take longer to reclaim freed memory.
Edit:
If you want to make sure the vector has capacity 0 it is pretty common to do the following:
v.swap(std::vector<char>());
assert(v.capacity() == 0);
What debugging tools did you use? Try yet deleaker! it is simple!