I have a class with private member variables declared in a header file. In my constructor, I pass in some filenames and create other objects using those names. This works fine. When I try to add another member variable, however, and initialize it in the constructor, I get an access reading violation. I sent the code to someone else and it works fine on his computer. Any idea what could be wrong?
Here is the offending code:
The .h file:
class QUERYMANAGER {
INDEXCACHE *cache;
URLTABLE *table;
SNIPPET *snip;
int* iquery[MAX_QUERY_LENGTH];
int* metapointers[MAX_QUERY_LENGTH];
int blockpointers[MAX_QUERY_LENGTH];
int docpositions[MAX_QUERY_LENGTH];
int numberdocs[MAX_QUERY_LENGTH];
int frequencies[MAX_QUERY_LENGTH];
int docarrays[MAX_QUERY_LENGTH][256];
int qsize;
public:
QUERYMANAGER();
QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname, char *snippetfname, char *snippetbtfname);
~QUERYMANAGER();
This is the .cpp file:
#include "querymanagernew.h"
#include "snippet.h"
using namespace std;
QUERYMANAGER::QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname, char *snippetfname, char *snippetbtfname){
cache = new INDEXCACHE(indexfname, btfname);
table = new URLTABLE(urltablefname);
snip = new SNIPPET(snippetfname, snippetbtfname);
//this is where the error occurs
qsize = 0;
}
I am totally at a loss as to what is causing this - any ideas?
Thanks, bsg
Suggestion, factor out the arrays:
class QUERYMANAGER
{
// Snip
int* iquery[MAX_QUERY_LENGTH];
int* metapointers[MAX_QUERY_LENGTH];
int blockpointers[MAX_QUERY_LENGTH];
int docpositions[MAX_QUERY_LENGTH];
int numberdocs[MAX_QUERY_LENGTH];
int frequencies[MAX_QUERY_LENGTH];
int docarrays[MAX_QUERY_LENGTH][256];
int qsize;
// Snip
};
Looks like you should have another structure:
struct Info
{
int* iquery;
int* metapointers;
int blockpointers;
int docpositions;
int numberdocs;
int frequencies;
int docarrays[256];
};
And the QueryManager now looks like:
class QueryManager
{
INDEXCACHE *cache;
URLTABLE *table;
SNIPPET *snip;
int qsize;
Info details[MAX_QUERY_LENGTH];
};
This may help encapsulate themes a little better.
Your dependencies are probably not right, and the necessary files aren't getting rebuilt. Try a "clean" rebuild.
As a note to style, use initializer lists.
QUERYMANAGER::QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname,
char *snippetfname, char *snippetbtfname) :
cache(new INDEXCACHE(indexfname, btfname)),
table(new URLTABLE(urltablefname)),
snip(new SNIPPET(snippetfname, snippetbtfname)),
qsize(0)
{
}
and you may not need to make those items pointers:
class QUERYMANAGER {
INDEXCACHE cache;
URLTABLE table;
SNIPPET snip;
...
QUERYMANAGER::QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname,
char *snippetfname, char *snippetbtfname) :
cache(indexfname, btfname),
table(urltablefname),
snip(snippetfname, snippetbtfname),
qsize(0)
{
}
Have you built clean? Since accessing the last member variable blows up, but assigning to earlier ones works OK, either you're not constructing/allocating the instance right when you do use it, or you have object files that refer to older versions of the header that didn't have qsize in the object yet, and thus aren't allocating enough space. Or something along those lines.
As expected, this runs just fine on my machine:
#include <cstdlib>
struct INDEXCACHE {};
struct URLTABLE {};
struct SNIPPET {};
const std::size_t MAX_QUERY_LENGTH = 256;
class QUERYMANAGER {
INDEXCACHE *cache;
URLTABLE *table;
SNIPPET *snip;
int* iquery[MAX_QUERY_LENGTH];
int* metapointers[MAX_QUERY_LENGTH];
int blockpointers[MAX_QUERY_LENGTH];
int docpositions[MAX_QUERY_LENGTH];
int numberdocs[MAX_QUERY_LENGTH];
int frequencies[MAX_QUERY_LENGTH];
int docarrays[MAX_QUERY_LENGTH][256];
int qsize;
public:
QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname, char *snippetfname, char *snippetbtfname);
};
QUERYMANAGER::QUERYMANAGER(char *indexfname, char *btfname, char *urltablefname, char *snippetfname, char *snippetbtfname)
: cache(new INDEXCACHE(/*indexfname, btfname*/))
, table(new URLTABLE(/*urltablefname*/))
, snip(new SNIPPET(/*snippetfname, snippetbtfname*/))
, qsize(0)
{
}
int main()
{
QUERYMANAGER foo("blargl", "frxnl", "wrgxl", "brlgl", "srgl");
return 0;
}
So the error must be in the code you're not showing.
BTW, all upper-case names are boo except for macros. They're making your code harder to read and confuse everyone used to a more common coding style.
Related
my code:
#include <iostream>
using namespace std;
struct widget
{
char brand[20];
int type;
union id
{
long id_num;
char id_char[20];
}id_val;
};
int main()
{
widget prize =
{"Rolls", 0, "A2X"};
return 0;
}
The problem is with initialization "A2X" when initializing a union in a structure. Compiler doesn't know I want to choose second option with array of chars when I am passing "A2X", it's requiring long type. When I put
char id_char[20]
before
long id_num
everything is ok. But I want to know how to enforce compiler to accept "A2X" with char as the second option in union. Thank for your help.
But I want to know how to enforce compiler to accept "A2X" with char as the second option in union.
You can use a constructor:
id(char const *id_char) {
std::strcpy(this->id_char, id_char);
}
Alternatively you could use a widget constructor.
A drawback is that the compiler probably won't be able to warn you if you use a too large input string for initialization. The shown trivial constructor can be expanded with strlen to check overflow at runtime. I suggest throwing an exception if you choose to check.
This works with -std=c++11:
#include <cstring>
#include <stdexcept>
struct widget
{
char brand[20];
int type;
union id
{
long id_num;
char id_char[20];
}id_val;
widget(char const*Str, int Type, char const *Id);
};
widget::widget(char const*Str, int Type, char const *Id)
{
if (strlen(Str)+1 > sizeof brand)
throw std::length_error{"brand too large"};
memcpy(brand,Str,strlen(Str)+1);
type = Type;
if (strlen(Id)+1 > sizeof id_val.id_char)
throw std::length_error{"id too large"};
memcpy(id_val.id_char,Id,strlen(Id)+1);
}
int main()
{
widget prize = {"Rolls", 0, "A2X"};
return 0;
}
i'm a iOS programer from china, I'm so sorry that i can't make an exact title for this question, but i'll try to describe it detailed. If there are any one can help me to change the title, i'm very thankful about that. Sorry for my bad English.
When i using clang -rewrite-objc to see the source code about the Block Syntax, i found there is something that i can't understand. Here is my code:
int main(int argc, char *argv[]) {
void (^blk)() = ^ {
};
blk();
}
And the core source code is
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(int argc, char *argv[]) {
void (*blk)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
}
In the main function, when i call the blk(), the source code cast blk and take the FuncPtr by this code
((__block_impl *)blk)->FuncPtr)
I can't really understand that, is it supposed to do? In my opinion, i prefer to use
(((__main_block_impl_0 *)blk ->impl).FuncPtr)
I don't really know more about C++, if there is anyone who can help me to understand the principle of this code, i'll be very thankful. Thanks for you guys.
Well, struct __main_block_impl_0's first member (impl) is a struct __block_impl. So the location of the struct __main_block_impl_0 is the same as the location of the struct __block_impl that is its first member. If you have the pointer to one you can just treat it as a pointer to the other.
Hi I am new in c++ and I make skeleton of program and I have some problems with destructors and constructors.
My head.cpp:
#include <iostream>
#include "set_char.hpp"
using namespace std;
int main()
{
set_char *z1 = new set_char(unsigned char *zbior[]);
delete z1;
return 0;
};
My set_char.hpp class file:
#define ROZMIAR_MAX 256
class set_char
{
unsigned char zbior[ROZMIAR_MAX];
public:
set_char(unsigned char *zbior[]);
~set_char(unsigned char *zbior[]);
int nalezy(unsigned char);
int licznosc();
void dodaj(unsigned char);
void usun(unsigned char);
};
And my set_char.cpp file:
#include "set_char.hpp"
#include <iostream>
#include <math.h>
using namespace std;
set_char(unsigned char *zbior[]);
~set_char(unsigned char *zbior[]);
void set_char::dodaj(unsigned char)
{
};
void set_char::usun(unsigned char)
{
};
int set_char::nalezy(unsigned char)
{
};
int set_char::licznosc()
{
};
Among others:
you should not add any parameters in destructors:
~set_char(unsigned char *zbior[]);
^^^^^^^^^^^^^^^^^^^^^^ --- remove it
When creating set_char you should provide pointer to your array, and not the actual parameter type:
set_char *z1 = new set_char(unsigned char *zbior[]);
^^^^^^^^^^^^^^^^^^^^^^
1
You did not define your Constructor and Destructor
You declared them both in your set_char.hpp
set_char(unsigned char *zbior[]);
~set_char(unsigned char *zbior[]);
However in set_char.cpp you re-declare them again without a return type. Defining a Constructor and Destructor outside of a class is illegal. Your compiler thinks they are functions and searches for a return type.
2
a Destructor may not have any arguments.
3
If you define an array as an argument in a Function or a Constructor or Destructor with brackets '[]', it may not be of variable length, thus it must be defined. If it is intended to be of variable length, it must be left out.
4
You are calling the constructor in a bad way using:
new set_char(unsigned char *zbior[]);
You already declared what arguments it takes, so hand it the arguments. A null pointer, for example.
The correct way to do it in set_char.hpp:
set_char(unsigned char *);
~set_char();
The correct way to do it in set_char.cpp:
set_char::set_char(unsigned char *zbior)
{
//Your definition
}
set_char::~set_char();
{
//Your definition
}
The correct way to do it in head.cpp:
set_char *z1 = new set_char(0x0);
Also side-note, usually using the define macro to define constants, is a C way. In C++ it is usually done with:
static const size_t ROZMIAR_MAX 256;
Second side-note. It is considered 'neater' code if you have your constants/functions and whatnot defined inside a namespace
this has already been posted several times, but none of the times have answered my case. Please help me with my 'error: data member initializer is not allowed' which appears under the equals signs. Here's the code with the problem in it.
//Player.cpp :Contains information about the player
#include <iostream>
#include <string>
#include "Main.cpp"
using namespace std;
void Player()
{
struct Player {
int Charma = 0;
unsigned int Hunger = 10;
unsigned int Energy = 50;
unsigned int Health = 100;
};
enum Race {
UNKNOWN,
DEAD,
HUMAN,
ORC,
GOBLIN,
ELF,
LIZARD,
CAT,
VAMPIRE,
WEREWOLF,
SNK
};
}
You are getting that error because you are initializing the variables when you are declaring a struct. This is not allowed. Instead, move the initialization into the constructor of the struct.
However that is not the only error in your code. You are defining the struct inside of the Player function (which should be the constructor). You need to switch those, so that you have the Player function inside of the Player struct. This way the struct will have a constructor where you can initialize the values. Another thing, don't #include .cpp files. It's a bad practice.
Your code should be something like this:
struct Player {
int Charma;
unsigned int Hunger;
unsigned int Energy;
unsigned int Health;
Player() : Charma(0), Hunger(10), Energy(50), Health(100)
{
// do other constructor stuff here
}
};
In another approach of idea, if you are planning on doing some mecanics inside Player, you may move the declaration inside a real class. You will then be able to scale your project a little more easily. Something like this:
Header
// #include "Item.h"
typedef enum RaceDef {
UNKNOWN,
DEAD,
HUMAN,
ORC,
GOBLIN,
ELF,
LIZARD,
CAT,
VAMPIRE,
WEREWOLF,
SNK
} PlayerRace;
class Player {
public:
Player(unsigned int Charma=0,
unsigned int Hunger=10,
unsigned int Energy=50,
unsigned int Health=100,
PlayerRace Race=HUMAN);
void attack(Player);
void slap(Player);
//void equipItem(Item);
void exercise(unsigned int duration);
void die();
void etc();
private:
unsigned int m_Charma;
unsigned int m_Hunger;
unsigned int m_Energy;
unsigned int m_Health;
unsigned PlayerRace m_Race;
Race m_Race;
};
CPP
Player::Player(unsigned int Charma,
unsigned int Hunger,
unsigned int Energy,
unsigned int Health,
PlayerRace Race):
m_Charma(Charma),
m_Hunger(Hunger),
m_Energy(Energy),
m_Health(Health),
m_Race(Race) {
//constructor code goes here
//e.g. if player starts with a random item :
// Item randomItem = ItemUtils.getRandomItem();
// equipItem(randomItem);
}
I hope this helps, and good luck :)
I'm changing the class implementation of a large class for a company project that has several static variables declared as private members of the class. There are many arrays and structs declared in the class header that utilize these static variables. I now need to assign the static data members values from my main function somehow. I tried assigning the static variables through the constructor but the header is declared prior to the constructor call so that wasn't possible.
For example, if I have
class Data
{
private:
static unsigned int numReadings = 10;
static unsigned int numMeters = 4;
unsigned int array[numMeters];
}
I would want to change it such that I could set numReadings and numMeters from my main function somehow, so it will allow all of my arrays and structs that utilize numMeters and numReadings to be initialized properly.
Is there a way to do this in C++? Of course I could always change my class design and set these in the constructor somehow but I'd like to avoid that if I can as it will take quite a long time.
You cannot do it in the main function, but you can do it in the main.cpp file:
// Main.cpp
#include <iostream>
#include "T.h"
using namespace std;
int T::a = 0xff;
int main()
{
T t; // Prints 255
return 0;
}
// T.h
#pragma once
#include <iostream>
using namespace std;
class T {
public:
T() { cout << a << endl; }
private:
static int a;
};
Have you tried making them public and accessing them with Data::numReadings = 10?
UPDATE:
#include <cstdlib>
using namespace std;
/* * */
class Asdf
{
public:
static int a;
};
int Asdf::a = 0;
int main(int argc, char** argv) {
Asdf::a = 2;
return 0;
}
Regardless of the accessibility of these variables, you need to define and initialize the static members outside the class definition:
// header
class Data
{
private:
static unsigned int numReadings;
static unsigned int numMeters;
unsigned int array[numMeters]; //<=see edit
};
// class implementation file
unsigned int Data::numReadings = 10;
unsigned int Data::numMeters = 4;
This is part of the implementation of the class and shouldn't be in the header (ODR rule).
Of course, if you want to access these variables (which are shared among all instances of the class) from outside, you need to make them public, or better, foresee and accessor.
Edit:
As the question is formulated around the static issue, I didn't notice the variable length array : this is not standard c++, although some compilers might accept it as a non-standard extension.
To do this properly, you should define a vector and initialize it at construction:
class Data
{
public:
Data ();
private:
static unsigned int numReadings;
static unsigned int numMeters;
vector<unsigned int> mycontainer; //<=for dynamic size
};
Data::Data() : mycontainer(numMeters) { } // initialize object with right size