I am trying to write a object oriented C++ code that is parallelized with OpenACC.
I was able to find some stackoverflow questions and GTC talks on OpenACC, but I could not find some real world examples of object oriented code.
In this question an example for a OpenACCArray was shown that does some memory management in the background (code available at http://www.pgroup.com/lit/samples/gtc15_S5233.tar).
However, I am wondering if it is possible create a class that manages the arrays on a higher level. E.g.
struct Data
{
// OpenACCArray<float> a;
OpenACCArray<Vector3<float>> a3;
Data(size_t len) {
#pragma acc enter data copyin(this)
// a.resize(len);
a3.resize(len);
}
~Data() {
#pragma acc exit data delete(this)
}
void update_device() {
// a.update_device();
a3.update_device();
}
void update_host() {
// a.update_host();
a3.update_host();
}
};
int main(int argc, char *argv[])
{
const size_t len = 32*128;
Data d(len);
d.update_device();
#pragma acc kernels loop independent present(d)
for (int i=0; i < len; ++i) {
float val = (float)i/(float)len;
d.a3[i].x = val;
d.a3[i].y = i;
d.a3[i].z = d.a3[i].x / d.a3[i].y;
}
d.update_host();
for (int i=0; i < len/128; ++i) {
cout << i << ": " << d.a3[i].x << "," << d.a3[i].y << "," << d.a3[i].z << endl;
}
cout << endl;
return 0;
}
Interestingly this program works, but as soon as I uncomment OpenACCArray<float> a;, i.e. add another member to that Data struct, I get memory errors.
FATAL ERROR: variable in data clause is partially present on the device.
Since the OpenACCArray struct is a flat structure that handles the pointer indirections on its own it should work to copy it as member?
Or does need to be a pointer to the struct and the pointers have to be hardwired with directives?
Then I fear the problem that I have to use alias pointers as suggested by jeff larkin at the above mentioned question.
I don't mind doing the work to get this running, but I cannot find any reference how to do that.
Using compiler directives keepgpu,keepptx helps a bit to understand what the compiler is doing, but I would prefer an alternative to reverse engineering generated ptx code.
Any pointers to helpful reference project or documents are highly appreciated.
In the OpenACCArray1.h header, remove the two "#pragma acc enter data create(this)" pragmas. What's happening is that the "Data" constructor is creating the "a" and "a3" objects on the device. Hence, when the second enter data region is encountered in the OpenACCArray constructor, the device this pointer is already there.
It works when there is only one data member since "a3" and "Data" share the same address for the this pointer. Hence when the second enter data pragma is encountered, the present check sees that it's already on the device so doesn't created it again. When "a" is added, the size of "Data" is twice that of "a", hence the present check sees that the this pointer is already there but has a different size than before. That's what the "partially present" error means. The data is there but has a different than expected size.
Only the parent class/struct should create the this pointer on the device.
Hope this helps,
Mat
Related
This question already has answers here:
Can I access private members from outside the class without using friends?
(27 answers)
Closed 2 years ago.
I have a homework in which:
we have this code:
#include <iostream>
using namespace std;
class Test {
int x;
char y;
public:
Test() :x(0), y(0) { ; }
};
int main() {
Test t;
//Do stuff!
return 0;
}
and without adding getters and setters or using friend class we have to read x and y and also change them.
I searched and found these ways:
if there was a template function in my class I could say:
class Test {
int x;
char y;
public:
Test() :x(0), y(0) { ; }
template<typename T>
void do_something() {//not necessarily void function
//Do some stuff
};
};
class a;
// My specialization.
template <>
void Test::do_something<a>() {
cout << x << endl;
cout << y << endl;
// getting data
x = 5;
y = 'a';
// changing data
cout << x << endl;
cout << y << endl;
// getting data after changes we made
}
int main() {
Test t;
t.do_something<a>();
return 0;
}
and also the method, which I think is this question answer, is using pointers.
like this:
class Test {
int x;
char y;
public:
Test() :x(0), y('0') { ; }
};
int main() {
Test t;
int* ptr = (int*)&t;
cout << "x = " << *ptr << " y = " << (char)*(ptr + 1) << endl;
*ptr--;
//getting data
*ptr = 12;
ptr++;
*ptr = 65;
//changing data
ptr--;
cout << "x = " << *ptr << " y = " << (char)*(ptr + 1) << endl;
//getting data after changes we have made
return 0;
}
or using reinterpret_cast and pointers:
struct pointer {
int x;
char y;
};
class Test {
int x;
char y;
public:
Test() :x(0), y('0') { ; }
};
int main()
{
Test t;
pointer* p = reinterpret_cast<pointer*>(&t);
cout << "X = " << p->x << " Y = " << p->y << endl;
//getting data
p->x = 5;
p->y = 'a';
//changing data
cout << "X = " << p->x << " Y = " << p->y << endl;
//getting data from class after changing them with pointers
return 0;
}
my questions are:
is such thing possible in other object oriented languages?
does this mean access modifiers are useless?
and is there anything we can do to prevent such thing to happen?
(with pointers) why this happen?
I don't understand this one, so I will skip it.
is such thing possible in other object oriented languages?
Consider python. In python making something private is explicitly only an agreement between the author and the user, but nothing prevents a user from accessing private members. Though, they should not. C++ isn't that explicit about saying "if you want you can access private members", but still it is possible with some effort. Nevertheless you should not. C++ does not prevent you from shooting yourself in your foot and accessing private members is one way of doing that. It isn't the case in your example, but typically accessing private members directly will break the object beyond repair.
does this mean access modifiers are useless?
I'll repeat my comment: Is a traffic light useless? I mean when it is red I can still cross the street. Access specifiers are not there to prevent you from doing something wrong by all means, they are to help you to avoid doing something wrong (and if you try hard you can still do something wrong).
and is there anything we can do to prevent such thing to happen?
Declaring a member as private is enough to signal that a user should not access the member directly by any means. If someone wants to break that agreement then they can do it. You cannot prevent a user from doing something wrong. If they want to break your class they can do so. However, it is not your responsibility to guarantee that something broken still works as expected. If a user bypasses access specifiers then they broke the agreement between them and you. Consider you buy a laptop and throw it out of the window from 42th floor. Will you complain to the manufacturer that afterwards the laptop is not working properly anymore? I guess no, instead you will understand that you made something wrong with using your laptop.
PS: Your last two examples are undefined behavior. reinterpret_cast is not a way to cast between arbitrary types magically. The set of allowed casts and what you can do with the results is in fact rather limited (see here). Also a c-style cast enables you do to casts that can be very wrong, without your compiler complaining about it. Thats why they should be avoided in favor of the proper c++ casts (static_cast et al).
Answering your question 4, is there anything we can do to prevent such thing to happen?:
It is indeed a language design problem that code using a class in C++ is typically able to see the inner makeup of a class. A visible, complete class definition is clearly a breach of information hiding. It's necessary though because of the "by-value semantics" of C++ that it inherited from C and which distinguishes it from, say, C# or Java.
One of the consequences is what you describe: That users can easier access object data they are not opposed to. (To be fair, with enough malicious energy that is unpreventable in the general sense no matter the precautions, but knowing the class layout allows you to do so with less "criminal effort", in this case through normal language means. Another, even simpler way which I recall was buried in one large project when it went open source was to simply #define private public before including the header in question.)
A second, more relevant problem is that code which uses objects of that class, or one of its descendants, is too tightly coupled with that class; it knows more than it should or needs to. Any trivial change to the class makes it necessary to recompile all code which includes its definition, directly or indirectly. For large projects with elaborate class hierarchies touching a base class may cause a senseless re-build of the whole project.1
To finally answer your question: The canonical C++ strategy to reduce this coupling are compilation firewalls. You essentially define an interface of pure virtual functions and no data, which should be relatively stable. User code sees only that interface. By that you gain information hiding and the power of polymorphism. But because you cannot directly handle objects any longer but only pointers or references, you lose the advantages of C++'s by-value paradigm (speed, no aliasing).
1 In a job interview in 1998 or so as C++ developer at Star Division, which was developing StarOffice, the original precursor to OpenOffice and LibreOffice, I was asked: "You have a base class, directly or indirectly used throughout the project. Now you would like to add a virtual function to it but avoid recompilation of the whole project, because it would just take too long. Can you do that? How?" The answer is that most implementations probably maintain the virtual functions in a vtable to which you can append without changing the offsets of existing functions (and, of course, without altering the object layout). Obviously, there is no guarantee that the implementation does not generate the vtable backwards, or employs some other mechanism, but in practice that's what you can do.
In my program, I'm trying to dereference a pointer to a struct Article, to get its id, but I'm getting "Access violation reading location 0xCCCCCCCC". I've tried many different things, local variables, backtracking the pointers back into the code, different parentheses... nothing though. I'm out of options and I can't see the problem however hard I try.
There might be an answer to this question, but access violation is much too general for me to be able to find the answer I'm looking for (also most of the questions go around arrays, which aren't my case).
Here I define a simple struct to keep my data.
struct Article {
public:
std::string id;
std::string title;
std::string text;
Article(std::string article_id, std::string article_title, std::string article_text) : id(article_id), title(article_title), text(article_text) {};
void toString();
};
Next, I use a dictionary that maps all words to the articles where they appear. The code is not done itself, but maps of words should include all the necessary pointers.
std::map<std::string, std::map<Article*, unsigned>> word_dict_;
I also keep another vector<Article> articles_ wher I keep all of them, so no null pointers should appear in the word_dict_;
Here the dictionary gets generated.
void fulltext::generateDict() {
for (Article ar : articles_) {
unsigned wordStart;
bool isBuilding = false;
string buffer = "";
for (unsigned int it = 0; it <= ar.text.size(); ++it) {
char c;
if (it < ar.text.size())
c = ar.text.at(it);
else
c = '\0';
if (isalpha(c)) {
// start or middle of word
if (!isBuilding) {
isBuilding = true;
wordStart = it;
}
buffer += c;
}
else {
isBuilding = false;
if (buffer != "") {
stringToLower(buffer); // rewrites buffer to low case
// Here I tried creating &ar just for the laughs and it works just fine.
word_dict_[buffer][&ar] = wordStart;
buffer = "";
}
}
}
}
}
Last but not least, I want to have it printed out and here the real fun starts.
void fulltext::printWordDict() {
cout << "Printing generated word dictionary: " << endl;
for (auto wordPair : word_dict_) {
cout << " \" " << wordPair.first << " \" " << endl;
cout << "There are " << wordPair.second.size() << " inputs." << endl;
for (pair<Article*, unsigned int> articlePair : wordPair.second) {
cout << (articlePair.first)->id << endl; // Here the access violation occurs
// Nothing seemingly works
// cout << articlePair.first->id; ... Access violation
// cout << (*articlePair.first).id; ... Access violation
// auto ar = articlePair.first; cout << ar->id; ... access violation
// auto ar = articlePair.first; cout << (*ar).id; ... access again
}
cout << endl;
}
cout << "Done." << endl;
}
These functions are called from within a main function fulltext::proccess() coincidentally in immediate succession. The word_dict_ is class private variable.
If there's need for any other parts of the code, just let me know, although none of the others should make any issues in this case.
for (Article ar : articles_) {
...
word_dict_[buffer][&ar] = wordStart;
...
}
Here you are storing a pointer to ar in your dictionary, however ar is destroyed at the end of its scope - when your for loop ends. So now you are storing a dangling pointer in your map, which you cannot de-reference.
Store Article objects in your map instead of Article* , or otherwise ensure the Article object lives somewhere as long as you have a pointer to it in your map.
If you have the objects live in your articles_ container, you might not need to copy it in your for loop, and instead do:
for (Article& ar : articles_) {
..
word_dict_[buffer][&ar] = wordStart;
Now you'll get a pointer to your Article object that resides within article_.
Though be aware what you do with article_ later on - if you perform operations on it that moves objects around (which can happen for many reasons depending on the container type), your pointers within word_dict_ becomes invalid.
for (Article ar : articles_)
This performs a copy of your article, as a local variable. This local variable goes out of scope as soon as the next iteration of the loop rolls around.
word_dict_[buffer][&ar] = wordStart;
Here you store a pointer to the local variable, that is valid only inside your loop.
If you can ensure that your articles will outlive your map, you can store a pointer to the articles stored in articles_. Take note, that if articles_ is a std::vector, it might get reallocated when you insert new articles into it, so storing pointers to object inside it has to be done carefully, making sure to invalidate them when the std::vector changes.
If all of the above sounds like your cup of tea, You most probably want to create a reference to the article, like so
for (Article& ar : articles_)
If the above sounds a bit too complicated, you have 2 possible approaches.
Make your word_dict_ map store Article objects by Value, instead of as pointers. Downside of this approach is that you store your articles twice, which has logical implications (changes to the article inside your map won't be reflected in the articles_ vector and vice-versa) as well as memory implications (you use double the memory)
Make your articles_ vector store std::unique_ptr<Article>. This way, you won't need to manually manage the reallocations inside your vector. You will still need to manage the case where an Article is removed from the articles_ vector, and make sure to remove it from the word_dict_ map. The downside of this approach is that it makes your class uncopiable by default (std::unique_ptr has a deleted copy constructor), which might or might not be a problem for you. If you need them to be copied, you would need to manually provide a copy ctor and copy assignment operator, as well manually implement or = default the other 3 special member functions (see Rule of 5)
We are under a PCI PA-DSS certification and one of its requirements is to avoid writing clean PAN (card number) to disk. The application is not writing such information to disk, but if the operating system (Windows, in this case) needs to swap, the memory contents is written to page file. Therefore the application must clean up the memory to prevent from RAM capturer services to read sensitive data.
There are three situations to handle:
heap allocation (malloc): before freeing the memory, the area can be cleaned up with memset
static or global data: after being used, the area can be cleaned up using memset
local data (function member): the data is put on stack and is not accessible after the function is finished
For example:
void test()
{
char card_number[17];
strcpy(card_number, "4000000000000000");
}
After test executes, the memory still contains the card_number information.
One instruction could zero the variable card_number at the end of test, but this should be for all functions in the program.
memset(card_number, 0, sizeof(card_number));
Is there a way to clean up the stack at some point, like right before the program finishes?
Cleaning the stack right when the program finishes might be too late, it could have already been swapped out during any point at its runtime. You should keep your sentitive data only in memory locked with VirtualLock so it does not get swapped out. This has to happen before said sensitive data is read.
There is a small limit on how much memory you can lock like this so you can propably not lock the whole stack and should avoid storing sensitive data on the stack at all.
I assume you want to get rid of this situation below:
#include <iostream>
using namespace std;
void test()
{
char card_number[17];
strcpy(card_number, "1234567890123456");
cout << "test() -> " << card_number << endl;
}
void test_trash()
{
// don't initialize, so get the trash from previous call to test()
char card_number[17];
cout << "trash from previous function -> " << card_number << endl;
}
int main(int argc, const char * argv[])
{
test();
test_trash();
return 0;
}
Output:
test() -> 1234567890123456
trash from previous function -> 1234567890123456
You CAN do something like this:
#include <iostream>
using namespace std;
class CardNumber
{
char card_number[17];
public:
CardNumber(const char * value)
{
strncpy(card_number, value, sizeof(card_number));
}
virtual ~CardNumber()
{
// as suggested by #piedar, memset_s(), so the compiler
// doesn't optimize it away.
memset_s(card_number, sizeof(card_number), 0, sizeof(card_number));
}
const char * operator()()
{
return card_number;
}
};
void test()
{
CardNumber cardNumber("1234567890123456");
cout << "test() -> " << cardNumber() << endl;
}
void test_trash()
{
// don't initialize, so get the trash from previous call to test()
char card_number[17];
cout << "trash from previous function -> " << card_number << endl;
}
int main(int argc, const char * argv[])
{
test();
test_trash();
return 0;
}
Output:
test() -> 1234567890123456
trash from previous function ->
You can do something similar to clean up memory on the heap or static variables.
Obviously, we assume the card number will come from a dynamic source instead of the hard-coded thing...
AND YES: to explicit answer the title of your question: The stack will not be cleaned automatically... you have to clean it by yourself.
I believe it is necessary, but this is only half of the problem.
There are two issues here:
In principle, nothing prevents the OS from swapping your data while you are still using it. As pointed out in the other answer, you want VirtualLock on windows and mlock on linux.
You need to prevent the optimizer from optimizing out the memset. This also applies to global and dynamically allocated memory. I strongly suggest to take a look at cryptopp SecureWipeBuffer.
In general, you should avoid to do it manually, as it is an error-prone procedure. Instead, consider using a custom allocator or a custom class template for secure data that can be freed in the destructor.
The stack is cleaned up by moving the stack pointer, not by actually popping values from it. The only mechanics are to pop the return into the appropriate registers. You must do it all manually. Also -- volatile can help you avoid optimizations on a per variable basis. You can manually pop the stack clean, but -- you need assembler to do that -- and it is not so simple to start manipulating the stack -- it is not actually your resource -- the compiler owns it as far as you are concerned.
I am making a text-based RPG with C++ and I'm having the same error pop up time and again, and I'm sure I'm doing something fundamentally wrong, but I don't know what. Searches turned up the solution to the specific compiler error, but not anything I can use to fix the code I'm writing.
Question I want answered: How do I use pointers to enable communication of variables between separate functions? In other words, how can I use pointers to point to a variable's value so that I can use and manipulate that value in a function in which it was not declared?
TL;DR version: I'm trying to make my "exp" int variable communicate with outside functions using pointers. I get the error "ISO C++ forbids comparison between pointer and integer [-fpermissive]"
Long version: Here's a bit of the code where I'm having problems:
In file charlvl.cpp:
...
int lvl = 1;
int *exp = 0;//value I want communicated to main()
int str = 0;
int vit = 0;
...
in file fight.cpp (main.cpp):
...
//you've just killed a monster
cout << "\nThe monster drops to the ground." << endl;
cout << "You gained " << expValue << " experience!" << endl;
&exp += expValue;//&exp is the character's experience.
//expValue is the exp gained upon monster death
//*exp (from charlvl.cpp) is the value I want to communicate to here.
It was not declared here, but in charlvl.cpp. How do I establish communication between the declared variable in charlvl.cpp and main() without having to resort to using global variables?
If you defined exp as a global pointer, you don't need to think about the communication thing, you can just simply use it in different functions, but the way you use it is wrong.
&exp += expValue;
should be change to
*exp += expValue;
because * means get that pointer's content to me.
btw, try not defining exp as a pointer may also work.
int exp = 0;
exp += expValue;
This is all based on exp is a global var or global pointer.
if you have defined it in a function like this:
void func()
{
int *expPtr = 0;
int exp = 0
}
And you want to use it in another function
void use()
{
// trying to use expPtr or exp.
}
The ways I know is:
1, use a local var and return it in func(), but be aware that the returned var is only a copy.
int func()
{
int exp = 0;
exp++;
return exp;
}
2, use a local pointer and allocate memory for it, then return the pointer or assign the new memory to a global pointer. But be careful about the memory leak, you need to delete it as soon as you don't use it.
int * func()
{
int *expPtr = 0;
expPtr = new int(2);
return expPtr;
}
You've gotten the & and * operators confused. * turns an int* into an int, while & turns an int* into an int**.
This is what you want:
(*exp) += expValue;
You might want to consider using references.
This program is written in C++. I am trying to use a void function to expand a Line structure which consists of an integer length and a pointer to the next connected line. There is a void Expand function made to assign a line reference to the line pointer in the struct. The new line is to be double the size of the current line. With the code I am using, I get a g++ error of 'Taking address of temporary [-fpermissive]'. Could anyone suggest a way in which the function adds a valid instance of a line reference to the Line pointer nextLine?
struct Line
{
int length;
Line* nextLine;
};
Line NewLine(Line& lineRef)
{
Line newLine;
newLine.length = lineRef.length * 2;
return newLine;
}
void Expand(Line& lineRef)
{
//Error here states: Taking address of temporary [-fpermissive]
lineRef.nextLine = &NewLine(lineRef);
}
int main() {
Line line;
Expand(line);
cout << line.length << endl;
cout << line.nextLine->length << endl;
return 0;
}
You're trying to implement a linked list, but you don't understand manual memory management yet.
The short-term solution is to use std::list<Line>. There's already a solution that works, and you don't need to bother with the behind-the-scenes stuff.
The long-term solution also is to use std::list<Line>. No need to re-invent the wheel, even if you're a seasoned developer and know how to.
The problem with the line:
lineRef.nextLine = &NewLine(lineRef);
is what the compiler is telling you. You are taking the address of a temporary. What it means is that after the ; is reached, the temporary NewLine(lineRef) will be destroyed and the pointer lineRef.nextLine will be pointer to a dead object.
Update: how to make it work.
It depends on what you want to do. If what you want is to have a list then the simplest thing is using a prepacked list data structure (std::list<Line>) rather than rolling your own implementation of list.
If you really want to implement your own list, then you will need to dynamically allocate the next node (this will make the compiler happy) and you will need to add code to manage the list (proper construction of the Line object that initializes the fields, including copy-construction, destructors to manage the dynamic memory, probably some helper functions to walk the list (or iterators to be able to use algorithms...) Just don't bother and use std::list.
This one works
struct Line
{
int length;
Line* nextLine;
~Line(){delete nextLine;}
//Make copy constructor and assignment operator private
};
void Expand(Line* lineRef)
{
lineRef->nextLine = new Line;
lineRef->nextLine->length = 2*(lineRef->length) ;
}
int main()
{
Line* line = new Line;
line->length = 5;
Expand(line);
cout << line->length << endl;
cout << line->nextLine->length << endl;
delete line;
return 0;
}