Memory Error using lambda function with array - c++

const int bookBoatNum = 10;
Wt::WPushButton *buttonBookBoat[bookBoatNum];
Wt::WDialog *dialogBookBoat[bookBoatNum];
for (int i = 1; i < bookBoatNum; i++){
dialogBookBoat[i] = new Wt::WDialog("Book Boat");
buttonBookBoat[i] = new Wt::WPushButton();
buttonBookBoat[i]->clicked().connect(std::bind([&dialogBookBoat,i]() {
dialogBookBoat[i]->show();
}));
}
The program compiles and runs. When I click on a WPushButton object, it crashes because of the third last line because of a memory error. This code works perfectly if buttonBookBoat and dialogBookBoat are single objects, rather than an array of objects. show() is a method that displays the dialog object.
Any help is appreciated, this error has been driving me crazy and my life is on the line with this code (not really).

const int bookBoatNum = 10;
Wt::WPushButton *buttonBookBoat[bookBoatNum];
Wt::WDialog *dialogBookBoat[bookBoatNum];
for (int i = 1; i < bookBoatNum; i++){
dialogBookBoat[i] = new Wt::WDialog("Book Boat");
Wt::WDialog * tempDialog=new Wt::WPushButton();
buttonBookBoat[i] = tempDialog;
buttonBookBoat[i]->clicked().connect(std::bind([tempDialog]() {
tempDialog->show();
}));
}
I think dialogBookBoat is an array so it will not exist after the function call.

Related

C++ pointers and arrays

I have a problem with dynamic array.
In header file class i have this:
class CTerrain
{
...
CRock *rocks;
int numRocks;//=0
...
}
and in cpp i have this:
void CTerrain::Create()
{
numRocks = 0;
int NUM_ROCKS = rand()%10+1;
for(int i=0;i<NUM_ROCKS;i++)
{
rocks = new CRock;
numRocks++;
...
}
}
void CTerrain::Render()
{
for(int i=0;i<numRocks;i++)
rocks[i].render();//it works ok when here is 0 instead of 'i'
}
When I run this code I got error:
Unhandled exception at 0x00913aea in OpenGL.exe: 0xC0000005: Access violation reading location 0x1c00001f.
Thanks for any help, I have been trying to resolve this problem for like 4 hours...
EDIT:
Ok, so I changed Create() method to this:
void CTerrain::Create()
{
numRocks = 0;
int NUM_ROCKS = rand()%10+1;
rocks = new CRock[NUM_ROCKS];
for(int i=0;i<NUM_ROCKS;i++)
{
rocks[i].position = ...
numRocks++;
...
}
and also added delete [] rocks and now it's working.
Your Create function would be more like
void CTerrain::Create()
{
int NUM_ROCKS = rand()%10+1;
rocks = new CRock[NUM_ROCKS];
numRocks = NUM_ROCKS;
for(int i=0; i<NUM_ROCKS; i++)
{
rocks[i] = CRock{};
}
}
Just to add bit of explanation to above answer. Here:
for(int i=0;i<NUM_ROCKS;i++)
{
rocks = new CRock;
numRocks++;
...
}
What you do is, each time assign new instance of CRock to the pointer rock; thereby losing reference to the old object and creating memory leaks. Use a solution similar suggester by Cyber.
First off, rocks is pointer to CRocks. Your implemenation:
rocks[i].render() should be something like this:
rocks = new CRock [x]; (where x is the number of objects of type CRock.)
rocks[i] -> render().
delete rocks[i] // Just be sure to delete.
You may want to reference this for your solution on handling how a dynamic array of objects.
This other reference is good.
rocks = new CRock;
you overwrite CRock* pointer rocks in this line over and over again
Use this
rocks = new CRock[NUM_ROCKS];

Creating new objects in C++ function causes program to crash

I have a program which allows the user to play Dominoes against 3 CPU players, with varying difficulty. Each CPU player can be either Beginner, Intermediate or Expert, and each difficulty has it's own class. If I initiate my 3 CPU players at the beginning of my 'Window' class (below), the program runs fine.
In Window.h
public:
Window(QWidget *parent = 0);
Intermediate *cpu1;
Beginner *cpu2;
Intermediate *cpu3;
In Window.cpp
Window::Window(QWidget *parent):QDialog(parent) {
cpu1 = new Intermediate;
cpu2 = new Beginner;
cpu3 = new Intermediate;
}
However I want the user to be able to select the CPU difficulties at the beginning of the game, so I now have a function within 'Window' that creates the objects. As soon as I call this function the game freezes and I get an error message pop up saying telling me the program has ended unexpectedly.
void Window:: startGame(){
cpu1 = new Intermediate;
cpu2 = new Beginner;
cpu3 = new Intermediate;
}
If anyone would be able to explain to me what is going on and what I can do to get around this that would be great.
Intermediate.cpp (Beginner.cpp is almost identical)
#include "intermediate.h"
Intermediate::Intermediate()
{
tilePlaced = false;
skipGo = false;
}
void Intermediate::findDoubles(int a[7][2]){
for(int i = 0; i < 7; i++){ // Creates new doubles list after each go.
doublesList[i] = 0;
}
for(int i = 0; i < 7; i++){ // Creates a list of doubles
if ((a[i][0] == a[i][1]) && (a[i][0] != 7)){
doublesList[a[i][0]] = 1;
}
}
}
bool Intermediate::addDomino(){} // Function that finds best domino to replace and returns bool
if(tilePlaced == false){
pass++;
text += "\nPassed turn";
return false;
}
else{
pass = 0;
text += QString("\nPlaced [%1 : %2]").arg(a).arg(b);
return true;
}
}
One way to start would be to narrow down which class is causing the fault. Does it work if they are all Beginner, or if they are all Intermediate? If so then the other one is causing the problem.

C++ dereferencing an instance

I'm new to C++ and I'm trying to dry up my code, for example:
void gethit () {
Gert.hitbox(AA.x, AA.damage);
Gert.hitbox(AB.x, AB.damage);
Gert.hitbox(AC.x, AC.damage);
Gert.hitbox(AD.x, AD.damage);
Gert.hitbox(Terbil.x, Terbil.damage);
}
AA, AB, AC, AD and Terbil are all instances of a class called Entity with variables x and damage.
Every time I want to add a new instance I'll have to come into this function and add it manually. I'm trying to add all of the address of the instances to an array like so:
void * p_enemys[10];
p_enemys[0] = &AA;
p_enemys[1] = &AB;
p_enemys[2] = &AC;
p_enemys[3] = &AD;
p_enemys[4] = &Terbil;
Just wondering how I could call a function from the instance via the array, I tried to do
for(int i = 0; i < 10; i++;) {
Gert.hitbox(p_enemys[i].x, p_enemys[i].damage);
}
and g++ compiler spits out: "request for member `damage' in `p_enemys[i]', which is of non-aggregate type `void *'"
I don't really need to use arrays specifically any help is very appreciated.
Changes made, thanks #gldraphael!
vector <Entity*> p_Enemys(10);
void gethit () {
for (int i = 0; i < 10; ++i) {
Entity * ienemy = (Entity*) p_Enemys[i];
Gert.hitbox((ienemy->x), (ienemy->damage));
}
}
You can make an a std::vector as follows:
std::vector <Entity*> p_Enemys(10);
The assigning part remains the same:
p_enemys[0] = &AA;
p_enemys[1] = &AB;
p_enemys[2] = &AC;
p_enemys[3] = &AD;
p_enemys[4] = &Terbil;
You can then loop through the p_enemys as follows:
for(auto i : p_enemys) {
Gert.hitbox(i->x, i->damage);
}
So what was it that you missed?
The array was declared as an array of void*
So, in the loop, p_enemys[i] returned a void*.
Also class/struct members are accessed using a dereferencing operator ->. You used the membership operator . instead.
So this code should have worked instead:
for(int i = 0; i < p_enemys.size(); i++;) { //
Entity * ienemy = (Entity*) p_enemys[i]; // cast the void* into a Entity*
Gert.hitbox(ienemy->x, ienemy->damage);
}
As a general rule, avoid void*s whenever possible.

Strange errors: EXC_BAD_ACCESS in my class

Here is my code:
typedef struct TItemSelector{
ItemSelectFrame* pItems[2];
} SItemSelector;
class item {
public:
void expMethod();
SItemSelector itemSelector_;
UILayerButton* startBtn_;
};
void item::expMethod(){
startBtn_ = new UILayerButton();
for (i = 0; i < 3; i++) {
itemSelector_.pItems[i] = new ItemSelectFrame();
}
startBtn_->callMethodA();
}
void UILayerButton::callMethodA()
{
this->callMethodB();
}
void UILayerButton::callMethodB()
{
}
On this->callMethodB();, a "EXC_BAD_ACCESS" occoured.
After that I found a work-around:
class item {
public:
void expMethod();
SItemSelector itemSelector_;
SItemSelector itemSelector2_; // work around
UILayerButton* startBtn_;
};
Then everything goes well... I just don't know what happened, but callMethodB() is just an empty method, there's nothing to do with it.
I'm using Apple LLVM 3.1, default setting.
UPDATE: Fixed my code.
In this code:
for (i = 0; i < 3; i++) {
itemSelector_.pItems[i] = new ItemSelectFrame();
}
you are writing over the end of itemSelector_.pItems because pItems is an array of length 2 but you are writing 3 elements.
That then overwrites startBtn_ which happens to appear immediately after itemSelector_ in memory. And that explains the error when you subsequently read the now corrupted startBtn_.
Either change your loop termination test, or increase the length of pItems. I can't tell which one is the correct solution, but clearly you will know.

Trouble with byte array marshaling in ObjC/C++ to C# in IOS

** This is still unsolved **
I'm trying to call an ObjC/C++ function code from C#. I've done my best to follow different example code, the latest being mostly from:
http://msdn.microsoft.com/en-us/library/ms146631(v=VS.80).aspx
This is for an iPhone/MonoTouch environment, so I'm not sure I've done everything I should. The bytes appear to be ok in the ObjC/C++ function, but the byte array I get back into C# ends up containing 0 0 0 0 0 0 etc.
** Update **
Corrected for loop initializer, and now its giving a EXC_BAD_ACCESS signal on the *returnbytes[i] = bytes[i]; line.
C# code:
[DllImport ("__Internal")]
private static extern int _getjpeg(string url,ref IntPtr thebytes);
void somefunction(string image_id) {
int maxsize = 50000;
byte[] thebytes = new byte[maxsize];
IntPtr byteptr = Marshal.AllocHGlobal(maxsize);
int imagesize = _getjpeg(image_id,ref byteptr);
Debug.Log("Getting _picturesize()... "+ image_id);
int picsize = _picturesize();
Marshal.Copy(byteptr,thebytes,0,picsize);
var texture = new Texture2D(1,1);
string bytedebug = "";
for (int i=5000 ; i < 5020 ; i++)
bytedebug+=thebytes[i] + " ";
Debug.Log("Bytes length is "+imagesize);
Debug.Log("Bytes content is "+bytedebug);
}
C++/ObjC code:
int _getjpeg(const char* url,unsigned char** returnbytes) {
ALAsset* asset = [_pictures objectForKey:[NSString stringWithUTF8String:url]];
if(asset != NULL)
NSLog(#"_getjpeg() found URL: %#",[NSString stringWithUTF8String: url]);
else {
NSLog(#"_getjpeg() could not find URL: %#",[NSString stringWithUTF8String: url]);
return NULL;
}
UIImage *image = [UIImage imageWithCGImage: [asset thumbnail]];
NSData* pictureData = UIImageJPEGRepresentation (image, 1.0);
picturesize = (int)[pictureData length];
unsigned char* bytes = (unsigned char*)[pictureData bytes];
// This test does not give EXC_BAD_ACCESS
*returnbytes[5] = (unsigned int)3;
// updated below initializer in below for loop according to Eikos suggestion
for(int i=0 ; i < picturesize ; i++) {
// below lines gives EXC_BAD_ACCESS
*returnbytes[i] = bytes[i];
}
NSString* debugstr = [NSString string];
for(int i=5000; i < 5020 ; i++) {
unsigned char byteint = bytes[i];
debugstr = [debugstr stringByAppendingString:[NSString stringWithFormat:#"%i ",byteint]];
}
NSLog(#"bytes %s",[debugstr UTF8String]);
return picturesize;
}
Thanks
Keep in mind that the JPGRepresentation is probably not exactly the same as you put into it, so the length may differ.
In
for(int i;i < picturesize;i++) {
// *** Not sure I'm doing this correctly ***
*returnbytes[i] = bytes[i];
}
you forget to initialize i, so it might start with a random value which is bigger than picturesize, so the loop won't run at all.
You want unsigned char*, not **. You are passing a pointer in that is already allocated. A ** is for when you are passing in a pointer to variable that is itself a pointer to data: i.e. when the callee will allocate the memory and the caller wants to know about it.
Just pass in unsigned char* and then use
returnbytes[i] = bytes[i];
Alternatively, allocate in the calee and use an out, not a ref.