I am now working on a rather complex project involving control of a simulated robotic arm.
I finished a first version of the project and it is working fine.
I just added some new code that collect some information about the system at each iteration, save it in some arrays, and at the end prints everything in a file for later analysis.
Now, something real strange is happening. If I define the file in which the data will be saved as follow:
const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\ta";
everything works fine, exactly the same as it did before I add the new code (plus saving the data).
But if I define it as follow:
const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\tacit.txt";
then the system behaves in another way. Does not crash, but the robotic arm moves differently.
I tried to comment all the code that was making use of SAVEFILE, and even any new code related to data saving, but the problem persists.
I know that with only this information, it is unlikely that anybody can tell me what is wrong, but would anybody have some advice what direction to look ?
Would it make sense to think that a long string overwrite the value of some other variable ? How can it be possible ? Some guideline of clean C++ programming I might have broken ?
That some array is misbehaving sounds possible, and was the first thing I checked. I guess it should come from the arrays saving data, as they are the only new one. Thing is, even when I comment all the corresponding code, no change.
I try to give more information about my code. Here where I first use SAVEFILE (last argument of the runExperiment function)
int main(int argc, char *argv[]) {
std::vector<Controller*> controllers;
controllers.push_back(getConstrainedPDT(0,true));
controllers.push_back(getConstrainedPDT(1,true));
controllers.push_back(getConstrainedPDT(2,true));
runExperiment(controllers,LENGTHS,WEIGHTS,RADIUS,ANGLEMIN,ANGLEMAX,MAXTORQUES,PUSHVECTOR,GRAVITY,RUNTIME,TIMESTEP,XTARGET,YTARGET,ITERATIONSAVEDATA,SAVEFILE);
return 1;
}
and here the code of the function:
void runExperiment(std::vector<Controller*> controllers,const double * lengths, const double* weights, const double radius, const double* angleMin, const double* angleMax, const double* maxTorques,const double* pushVector,const dReal gravity,const dReal runTime,const dReal tstep,const dReal targetX,const dReal targetY,const int itSaveData,const std::string saveFile){
endTime = runTime;
simTime = 0.0;
timeStep = tstep;
dInitODE();
world = dWorldCreate();
space = dHashSpaceCreate(0);
contactgroup = dJointGroupCreate(0);
ground = dCreatePlane(space, 0, 0, 1, 0);
dWorldSetGravity(world, 0, 0, gravity);
createTargetObject(targetX,targetY);
int nbData = static_cast<int>( ( endTime / timeStep ) / static_cast<double>(itSaveData) );
robot = new R2DRobot(&world,controllers.size(),lengths,weights,radius,angleMin,angleMax,maxTorques,pushVector,controllers,itSaveData,nbData);
dsFunctions fn;
fn.version = DS_VERSION;
fn.start = &setViewPoint;
fn.step = &loop;
fn.stop = &stopSim;
fn.path_to_textures = PATH_TO_TEXTURES;
dsSimulationLoop(0, 0, 1280, 960, &fn);
dWorldDestroy(world);
dCloseODE();
// NOTE: commenting the next three lines does not fix the problem !
// it is the only place saveFile is used, except in the code of printData
// I do not show the code of printData as commenting it does not change anything
if (itSaveData>0){
robot->printData(saveFile);
}
delete robot;
}
In the hope to find the unspecified variable (not that easy for a project with a lot of classes, some of them virtual), I played with the const parameters and observed the behavior of the robot. I reached a situation:
works fine all the time:
const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\tacit.txt";
crashes the program:
const std::string SAVEFILE = "C:\\Users\\Vincent\\Desktop\\ta";
Now the issue is, if I add a single line to the code of runExperiment (call to printf added):
printf("experiment.cpp - 1 \n");
robot = new R2DRobot(&world,controllers.size(),lengths,weights,radius,angleMin,angleMax,maxTorques,pushVector,controllers,itSaveData,nbData);
then both versions of SAVEFILE work fine and do give exactly similar results.
Now, if I delete the call to printf and add in the constructor of R2DRobot:
R2DRobot::R2DRobot(dWorldID * world, const int nbLinks, const double * lengths, const double * weights, const double radius,const double* angleMin,const double* angleMax,const double* maxTorques,const double* pushVector, std::vector<Controller*> controllers,int saveData,int nbData):
Robot(3*nbLinks+3,controllers),pushVector(pushVector),nbLinks(nbLinks),weights(weights),angleMin(angleMin),angleMax(angleMax),maxTorques(maxTorques),itSaveData(saveData){
printf("experiment.cpp - 1 \n");
// rest of the code
then the program crashes (if using the short version of SAVEFILE) but after printing "experiment.cpp -1" in the console.
Same thing if I move the call to printf to the constructor of Robot, the mother class of R2DRobot.
This might be manifestation that your program does not initialize variables properly. When string was shorter, compiler created certain memory layout, and variables created on a stack (or on a heap) had certain values. By pure luck, those values were something that seemed to work right for you.
Now, since string has become longer, compiler has changed memory layout a little, and this led to slightly different layout. Now, these uninitialized variables might have slightly different values. It does not necessarily crash, but works differently.
but would anybody have some advice what direction to look
This information is really not enough, unfortunately. Maybe, you can try using valgrind or a similar tool to analyze your code.
Would it make sense to think that a long string overwrite the value of some other variable? How can it be possible?
No, this is not a long string. It's not even close to long string. If the string is too long, you'll have an exception for invalid length.
Some guideline of clean C++ programming I might have broken
Not enough information. Using std::string is good and it's even recommended.
The problem is somewhere else. Sounds like undefined behavior to me.
The height number of arguments to runExperiment with are global variables are telling you that you may need a higher level object to wrap and organize it. While trying to write a constructor for such an object you will probably see and correct the problem with the incorrect/un-initialized variables, with will prevent undefined behavior.
Related
I've been trying to learn a bit about reverse engineering and how to essentially wrap an existing class (that we do not have the source for, we'll call it PrivateClass) with our own class (we'll call it WrapperClass).
Right now I'm basically calling the constructor of PrivateClass while feeding a pointer to WrapperClass as the this argument...
Doing this populates m_string_address, m_somevalue1, m_somevalue2, and missingBytes with the PrivateClass object data. The dilemma now is that I am noticing issues with the original program (first a crash that was resolved by adding m_u1 and m_u2) and then text not rendering that was fixed by adding mData[2900].
I'm able to deduce that m_u1 and m_u2 hold the size of the string in m_string_address, but I wasn't expecting there to be any other member variables after them (which is why I was surprised with mData[2900] resolving the text rendering problem). 2900 is also just a random large value I threw in.
So my question is how can we determine the real size of a class that we do not have the source for? Is there a tool that will tell you what variables exist in a class and their order (or atleast the correct datatypes or datatype sizes of each variable). I'm assuming this might be possible by processing assembly in an address range into a semi-decompiled state.
class WrapperClass
{
public:
WrapperClass(const wchar_t* original);
private:
uintptr_t m_string_address;
int m_somevalue1;
int m_somevalue2;
char missingBytes[2900];
};
WrapperClass::WrapperClass(const wchar_t* original)
{
typedef void(__thiscall* PrivateClassCtor)(void* pThis, const wchar_t* original);
PrivateClassCtor PrivateClassCtorFunc = PrivateClassCtor(DLLBase + 0x1c00);
PrivateClassCtorFunc(this, original);
}
So my question is how can we determine the real size of a class that
we do not have the source for?
You have to guess or logically deduce it for yourself. Or just guess. If guessing doesn't work out for you, you'll have to guess again.
Is there a tool that will tell you what variables exist in a class and
their order (or atleast the correct datatypes or datatype sizes of
each variable) I'm assuming by decompiling and processing assembly in
an address range.
No, there is not. The type of meta information that describes a class, it's members, etc. simply isn't written out as the program does not need it nor are there currently no facilities defined in the C++ Standard that would require a compiler to generate that information.
There are exactly zero guarantees that you can reliably 'guess' the size of a class. You can however probably make a reasonable estimate in most cases.
The one thing you can be sure of though: the only problem is when you have too little memory for a class instance. Having too much memory isn't really a problem at all (Which is what adding 2900 extra bytes works).
On the assumption that the code was originally well written (e.g. the developer decided to initialise all the variables nicely), then you may be able to guess the size using something like this:
#define MAGIC 0xCD
// allocate a big buffer
char temp_buffer[8092];
memset(temp_buffer, MAGIC, 8092);
// call ctor
PrivateClassCtor PrivateClassCtorFunc = PrivateClassCtor(DLLBase + 0x1c00);
PrivateClassCtorFunc(this, original);
// step backwards until we find a byte that isn't 0xCD.
// Might want to change the magic value and run again
// just to be sure (e.g. the original ctor sets the last
// few bytes of the class to 0xCD by coincidence.
//
// Obviously fails if the developer never initialises member vars though!
for(int i = 8091; i >= 0; --i) {
if(temp_buffer[i] != MAGIC) {
printf("class size might be: %d\n", i + 1);
break;
}
}
That's probably a decent guess, however the only way to be 100% sure would be to stick a breakpoint where you call the ctor, switch to assembly view in your debugger of choice, and then step through the assembly line by line to see what the max address being written to is.
I've spent 2 days trying to figure this out and getting nowhere. Say I had a struct that looks like this:
struct Thing {
bool is_solid;
double matrix[9];
}
I want to create an array of that struct called things and then process that array on the GPU. Something like:
Thing *things;
int num_of_things = 100;
cudaMallocManaged((void **)&things, num_of_things * sizeof(Thing));
// Something missing here? Malloc individual structs? Everything I try doesn't work.
things[10].is_solid = true; // Segfaults
Is it even best practice to do it this way rather than pass a single struct with arrays that are num_of_things large? It seem to me that can get pretty nasty especially when you have arrays already (like matrix, which would need to be 9 * num_of_things.
Any info would be much appreciated!
After some dialog in the comments, it seems that OP's posted code has no issues. I was able to successfully compile and run this test case built around that code, and so was OP:
$ cat t1005.cu
#include <iostream>
struct Thing {
bool is_solid;
double matrix[9];
};
int main(){
Thing *things;
int num_of_things = 100;
cudaError_t ret = cudaMallocManaged((void **)&things, num_of_things * sizeof(Thing));
if (ret != cudaSuccess) {
std::cout << cudaGetErrorString(ret) << std::endl;
return 1;}
else {
things[10].is_solid = true;
std::cout << "Success!" << std::endl;
return 0;}
}
$ nvcc -arch=sm_30 -o t1005 t1005.cu
$ ./t1005
Success!
$
Regarding this question:
Is it even best practice to do it this way rather than pass a single struct with arrays that are num_of_things large?
Yes, this is a sensible practice and is usable whether managed memory is being used or not. An array of more or less any structure that does not contain embedded pointers to dynamically allocated data elsewhere can be transferred to the GPU in a simple fashion using a single cudaMemcpy call (for example, if managed memory were not being used.)
To address the question about the 3rd (flags) parameter to cudaMallocManaged:
If it is specified, it is not correct to pass zero (although OP's posted code gives no evidence of that.) You should use one of the documented choices.
If it is not specified, this is still valid, and a default argument of cudaMemAttachGlobal is provided. This can be confirmed by reviewing the cuda_runtime.h file or else simply compiling/running the test code above. This particular point appears to be an oversight in the documentation, and I've filed an internal issue at NVIDIA to take a look at that. So it's possible the documentation may change in the future with respect to this.
Finally, proper cuda error checking is always in order any time you are having trouble with a CUDA code, and the use of such may shed some light on any errors that are made. The seg fault that the OP reported in code comments was almost certainly due to the cudaMallocManaged call failing (perhaps because a zero parameter was supplied incorrectly) and as a result the pointer in question (things) had no actual allocation. Subsequent usage of that pointer would lead to a seg fault. My test code demonstrates how to avoid that seg fault, even if the cudaMallocManaged call fails for some reason, and the key is proper error checking.
I'm new to C++, coming from mostly working with Java and I'm having a problem with a function I'm trying to write. I'm sure it's something simple, but nonetheless, it's giving me fits, so prepare for a painfully newbie question.
I'm trying to write a function as follows:
void foo(u_char *ct){
/* ct is a counter variable,
it must be written this way due to the library
I need to use keeping it as an arbitrary user argument*/
/*here I would just like to convert the u_char to an int,
print and increment it for each call to foo,
the code sample I'm working from attempts to do it more or less as follows:*/
int *counter = (int *) ct;
printf("Count: %d\n", *counter);
*counter++;
return;
}
When I try to run this in XCode (something I'm also new to using), I get a EXE_BAD_ACCESS exception on the printf() portion of foo. I'm really not sure what is going on here but I suspect that it has something to do with conflating values, pointers and references, something I don't yet have a strong gasp of how C++ understands them coming from Java. Does anyone see where I'm slipping up here?
Thanks.
An u_char would be 1 byte in memory (the name suggests it's just an unsigned char), an int is typically 4 bytes. In printf, you tell the runtime to read an int (4 bytes) from the address where counter resides. But you only own 1 byte there.
EDIT (based on comments down here where poster says it's called actually with the address of an int: foo((u_char*)&count) ):
void foo(u_char *ct)
{
int *pcounter = (int *)ct; // change pointer back to an int *
printf("Count: %d\n", *pcounter);
(*pcounter)++; // <<-- brackets here because of operator precedence.
}
Or even shorter (the wild c-style for which everbody but newbies loves this language):
void foo(u_char *ct)
{
printf("Count: %d\n", (*(int *)ct)++);
}
First of all: I know that most optimization bugs are due to programming errors or relying on facts which may change depending on optimization settings (floating point values, multithreading issues, ...).
However I experienced a very hard to find bug and am somewhat unsure if there is any way to prevent these kind of errors from happening without turning the optimization off. Am I missing something? Could this really be an optimizer bug? Here's a simplified example:
struct Data {
int a;
int b;
double c;
};
struct Test {
void optimizeMe();
Data m_data;
};
void Test::optimizeMe() {
Data * pData; // Note that this pointer is not initialized!
bool first = true;
for (int i = 0; i < 3; ++i) {
if (first) {
first = false;
pData = &m_data;
pData->a = i * 10;
pData->b = i * pData->a;
pData->c = pData->b / 2;
} else {
pData->a = ++i;
} // end if
} // end for
};
int main(int argc, char *argv[]) {
Test test;
test.optimizeMe();
return 0;
}
The real program of course has a lot more to do than this. But it all boils down to the fact that instead of accessing m_data directly, a (previously unitialized) pointer is being used. As soon as I add enough statements to the if (first)-part, the optimizer seems to change the code to something along these lines:
if (first) {
first = false;
// pData-assignment has been removed!
m_data.a = i * 10;
m_data.b = i * m_data.a;
m_data.c = m_data.b / m_data.a;
} else {
pData->a = ++i; // This will crash - pData is not set yet.
} // end if
As you can see, it replaces the unnecessary pointer dereference with a direct write to the member struct. However it does not do this in the else-branch. It also removes the pData-assignment. Since the pointer is now still unitialized, the program will crash in the else-branch.
Of course there are various things which could be improved here, so you might blame it on the programmer:
Forget about the pointer and do what the optimizer does - use m_data directly.
Initialize pData to nullptr - that way the optimizer knows that the else-branch will fail if the pointer is never assigned. At least it seems to solve the problem in my test-environment.
Move the pointer assignment in front of the loop (effectively initializing pData with &m_data, which then could also be a reference instead of a pointer (for good measure). This makes sense because pData is needed in all cases so there is no reason to do this inside the loop.
The code is obviously smelly, to say the least, and I'm not trying to "blame" the optimizer for doing this. But I'm asking: What am I doing wrong? The program might be ugly, but it's valid code...
I should add that I'm using VS2012 with C++/CLI and v110_xp-Toolset. Optimization is set to /O2. Please also note that if you really want to reproduce the problem (that's not really the point of this question though) you need to play around with the complexity of the program. This is a very simplified example and the optimizer sometimes doesn't remove the pointer assignment. Hiding &m_data behind a function seems to "help".
EDIT:
Q: How do I know that the compiler is optimizing it to something like the example provided?
A: I'm not very good at reading assembler, I have looked at it however and have made 3 observations which make me believe that it's behaving this way:
As soon as optimization kicks in (adding more assignments usually does the trick) the pointer assignment has no associated assembler statement. It also hasn't been moved up to the declaration, so it's really left uninitialized it seems (at least to me).
In cases where the program crashes, the debugger skips the assignment statement. In cases where the program runs without problems, the debugger stops there.
If I watch the content of pData and the content of m_data while debugging, it clearly shows that all assignments in the if-branch have an effect on m_data and m_data receives the correct values. The pointer itself it still pointing to the same uninitialized value it had from the beginning. Therefore I have to assume that it is in fact not using the pointer to make the assignments at all.
Q: Does it have to do anything with i (Loop unrolling)?
A: No, the actual program actually uses do { ... } while() to loop over a SQL SELECT-resultset so the iteration count is completely runtime-specific and cannot be predetermined by the compiler.
It sure looks like an bug to me. It's fine for the optimizer to eliminate the unnecessary redirection, but it should not eliminate the assignment to pData.
Of course, you can work around the problem by assigning to pData before the loop (at least in this simple example). I gather that the problem in your actual code isn't as easily resolved.
I also vote for an optimizer bug if it is really reproducible in this example. To overrule the optimizer you could try to declare pData as volatile.
Trivial issue, but comes up a lot for me, and I imagine others too. Does anybody have a really good, really clever solution?
void some_function (obj &A, obj &B)
{
// do stuff with A...
//e.g.
double number_A = (value - A.member_func() ) * A.other_func();
// do stuff with B. similar BUT NOT EXACTLY like A...
//e.g.
double number_B = (value + B.member_func() ) * A.other_func();
// !!!!
// Big time TYPO - should say "B.other_func()", not "A.other_func()" !!!!
// !!!!
}
Any good guards against these types of errors?
I often have to work on two analogous variables, say one named version "A" and the other "B".
Because the code for each one is similar, I often use the code that worked on "A" as a "template" (i.e. copy & paste) for the code that works on "B" - making the small adjustments so that the code becomes appropriate for B.
Becuase I am human, I sometimes forget to change "A" to "B" in certain locations when copying the code. If I am lucky, this will cause the program to crash. Either way, this is disastrous.
Does anybody know any clever tricks for preventing such typos?
I've thought of...
enclosing brackets { } to try to restrict the scope of variables - but if objects A and B are in the function arguments, then this doesn't solve it.
dividing every function into sub-functions - one for A and one for B. This is a bit cumbersome from the developer perspective (passing/returning many of variables).
work only with pointers to the objects themselves - not the actual objects. This way we can { scope-control } the pointers. Also cumbersome, (and the overhead for defining a pointer is negligible, even if I call the function very, very often, right?)
In the example you give, the best defence is to do as little as possible in each function:
void some_function (obj &A, obj &B)
{
double number_A = do_stuff(A);
double number_B = do_similar_stuff(B);
}
double do_stuff(obj &A) {
return (value - A.member_func() ) * A.other_func();
}
// EITHER
double do_similar_stuff(obj &A) {
// no variable rename when copying == no problem
return value + A.member_func() ) * A.other_func();
}
// OR
double do_similar_stuff(obj &B) {
// A not in scope == very brief problem until compiler tells us
return value + B.member_func() ) * A.other_func();
// Beware, also, the nightmare scenario that there's some *other*
// `A` in scope, so this *still* compiles. For that reason, prefer
// the other option unless there's some good reason why this parameter
// should be `B`, and don't name member function parameters the same
// as data members etc.
}
Alternatively, you could make the relation between the two kinds of "stuff" explicit. Assuming that the unmatched parenthesis in your B code is supposed to go in the same place as the A. It all depends whether there really is a logical relationship between the two similar-looking operations:
void some_function (obj &A, obj &B)
{
double number_A = do_stuff(A, true);
double number_B = do_stuff(B, false);
}
double do_stuff(obj &A, bool subtract) {
// yeah, never call variables "tmp". Unless you have no context
// to give them meaning.
// Depending on the type of `tmp`, there might be a better way to
// write this, using multiplication by -1. But let's not assume, we'll do
// one refactor at a time.
auto tmp = subtract ? value - A.member_func() : value + A.member_func();
return tmp * A.other_func();
}
Other examples will vary. As you say it can be tiresome to write, but it has a number of benefits other than catching this error. Not least is that it will direct you towards writing your code in a way that you try to avoid passing/returning many variables. As a consequence, each line of your code affects fewer other things in the program, which is basic code hygiene.
It may also mean you can test that your formula with A is correct independently of whether your formula with B is correct, and sundry other benefits of short functions.
I have a few ideas in mind
you could use snippets if your editor supports them or move to an editor/ide which has support for them (personally I use kdevelop and snippets are very useful as they replace all occurences of a snippet variable)
you could also use refactoring (in a separate function if you
already used the names this one)
also selecting a piece of code and doing replace all in selection
might help
using defines is also an option
Still, going with a smarter IDE is the best in my opinion.
I think your best bet is not have similar function names in other classes. Also, having unit tests coupled with peer code reviews should catch these errors most of the time. However, there have been many times in SW history where these types of errors are never caught until many days, months, or years later.