The "IT DOESN'T WORK!" thread

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Thu May 24, 2012 6:24 pm UTC

Anyway. Component has a virtual function, virtual void receive(int, int) {};. The derived component, Collide, has an switch implemented in its member void receive(colmnessage message, int value).

receive(colmnessage, int) is not the same function as receive(int, int). Their signature differs.

When you defined receive(colmnessage, int), you did not override receive(int, int). You defined a brand new virtual function.

It is possible you just messed up types in the override. On the other hand, you might also be attempting to implement double dispatch, which C++ will not automagically do for you.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.
User avatar
Yakk
 
Posts: 10064
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby Shivahn » Thu May 24, 2012 6:34 pm UTC

Ohhhh duh. Yeah, I figured... since enum is sort of like an int, that...

Yeah. Duh ><.

What I want to do is override it, but I want to be able to pass these enum types, so that I can do something like receive(fire, 200) without having a huge #define or const int mess at the top of the page. Is there a way to do that?

If I understand double dispatch correctly, that would be making it so that being passed an int calls the base class function, and being passed a colmnessage would make it call the derived class' function. That is not what I'm trying to do here, I just wanted to override the base so that I could have a base-class-pointer list with an arbitrarily large number of types of derived class pointees in it that call their respective receive functions when asked.

Edit: Also, why doesn't it throw a compilation error at "(*it)->receive(collider->getMessage(), collider->getValue())"? collider->getMessage() returns the enumerated type, not int, so I would think it would complain "Component has no function void receive(colmnessage, int)".
User avatar
Shivahn
 
Posts: 2145
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby phlip » Thu May 24, 2012 11:47 pm UTC

enum values can be freely converted to ints, and you get the appropriate number. Converting an int back to an enum is also fine, but you need a cast.
Code: Select all
enum number
{
  zero, one, two, three, ten = 10, eleven // all the important numbers
};
enum number n; // can be just "number n;" in C++
int i;
i = two; // i == 2
n = 3; // Nope, compiler error
n = (enum number)3; // n == three -- in C++ you can also use static_cast<number>
n = (enum number)106; // undefined behavior

So if a function takes an int as a parameter, and you pass it an enum value, it'll happily convert it for you.
While no one overhear you quickly tell me not cow cow.
but how about watch phone?
User avatar
phlip
Restorer of Worlds
 
Posts: 6779
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia

Re: The "IT DOESN'T WORK!" thread

Postby Shivahn » Thu May 24, 2012 11:52 pm UTC

Ok, thanks! I'll just use ints as the receive type for all the functions, so they're properly shadowing the base, and throw an enum into it from the collider and cast it in the collidee, so that the code has a switch structure along the lines of "case fire: <stuff>; case water: <stuff>;", which should allow me to keep stuff readable.
User avatar
Shivahn
 
Posts: 2145
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby phlip » Thu May 24, 2012 11:56 pm UTC

Is there a reason you can't just use the enum in the base class too?
While no one overhear you quickly tell me not cow cow.
but how about watch phone?
User avatar
phlip
Restorer of Worlds
 
Posts: 6779
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia

Re: The "IT DOESN'T WORK!" thread

Postby Shivahn » Fri May 25, 2012 12:15 am UTC

Well, I'm making a game (or, screwing around making the base of one), and I want to make it as modular as possible. So, I am using an entity-component system, and the Component class is the base from which I've been having this problem. The component has a virtual receive function because many components are going to need the ability to receive something, and there might be cases where a component list contains components that I want to react differently to the same message - i.e., a ghost might ignore damage that doesn't come from a collider with the "ethereal" tag, or something.

I suppose I could have another component that does all the calculating later, so that each component just passes a message to the "calculate what happened this frame" part of the entity. Or, I could subclass Component to a class I won't instantiate, which will have the virtual void receive(colmessage, int) function for redefining in the base classes. Or I could just create several receives in the varying subclasses, and change my Component* lists to stuff like... Collision* lists, where Collision is itself a base for all colliding components.

The original base class can't have the enum, because there are other components that will want to receive different things, and I'd prefer not to have a really long enum with unrelated things if I can avoid it. It just seems like subpar design, though it'd work.

I guess all of the approaches have something I don't like, but now that you've mentioned it and gotten me thinking, I might go back and make Collision a Component derivative with its own virtual void receive(colmessage, int), and get rid of it entirely in the Component class. I don't like subclassing more than I have to, but this seems like it would probably be a fantastic place to do it if ever there was one.

Thanks a lot, I appreciate the suggestion. It made me think of better ways to do things, which is always excellent, especially early on.
User avatar
Shivahn
 
Posts: 2145
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby phlip » Fri May 25, 2012 3:47 am UTC

Thing is, the way you've described it, this "receive" method doesn't sound like it actually makes sense as a virtual method of your base class... If you have a function that takes some generic Component object, can that function generally call, say, component->receive(fire, 100)? From what you say, it sounds like the answer is no, as it might not accept that value. It sounds like you can't call the receive method anyway, unless you know what type of object you're working with... whether it's an object that can understand a "fire" message or not. So it's not really a part of your base class spec.
While no one overhear you quickly tell me not cow cow.
but how about watch phone?
User avatar
phlip
Restorer of Worlds
 
Posts: 6779
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia

Re: The "IT DOESN'T WORK!" thread

Postby Shivahn » Fri May 25, 2012 4:57 am UTC

You're right. I'm.. not super great with object-oriented design, I guess. It's something I'll have to work on.
User avatar
Shivahn
 
Posts: 2145
Joined: Tue Jan 06, 2009 6:17 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Wed May 30, 2012 11:34 pm UTC

I appear to have coded a class that travels backwards in time. Allow me to explain:

I have a function, `OrthogonalCamera::project()`, that sets a matrix to a certain value. I then print out the value of that matrix, as such.
Code: Select all
cam.project();

std::cout << "My Projection Matrix: " << std::endl << ProjectionMatrix::getMatrix() << std::endl;


cam.project() pushes a matrix onto ProjectionMatrix's stack (I am using the std::stack<Mat4> container), and ProjectionMatrix::getMatrix() just returns the stack's top element. If I run just this code, I get the following output:

Code: Select all
     2      0      0      0     
     0      7.7957 0      0     
     0      0      -0.001 0     
    -1     -1      -0.998 1   


But if I run the code with these to lines after the `std::cout` call
Code: Select all
float *foo = new float[16];

Mat4 fooMatrix = foo;


Then I get this output:
Code: Select all
     2      0      0      0     
     0     -2      0      0     
     0      0      -0.001 0     
    -1      1      -0.998 1   


Running it through the debugger gave me a third value when I reach the print step:
Code: Select all
    -7.559 0      0      0     
    0      -2     0      0     
    0      0      -0.001 0     
    1      1      -0.998 1   


My question is the following: what could I possibly be doing such that code that comes after I print a value changes the value being printed?

Some of the functions I'm using:

Code: Select all
static void load(Mat4 &set)
{
    if(ProjectionMatrix::matrices.size() > 0)
        ProjectionMatrix::matrices.pop();

    ProjectionMatrix::matrices.push(set);
}
static Mat4 &getMatrix()
{
    return ProjectionMatrix::matrices.top();
}


and

Code: Select all
void OrthogonalCamera::project()
{
    Mat4 orthProjection = { { 2.0f / (this->r - this->l), 0, 0, -1 * ((this->r + this->l) / (this->r - this->l)) },
    { 0, 2.0f / (this->t - this->b), 0, -1 * ((this->t + this->b) / (this->t - this->b)) },
    { 0, 0, -2.0f / (this->farClip - this->nearClip), -1 * ((this->farClip + this->nearClip) / (this->farClip - this->nearClip)) },
    { 0, 0, 0, 1 } }; //this is apparently the projection matrix for an orthographic projection.

    orthProjection = orthProjection.transpose();

    ProjectionMatrix::load(orthProjection);
}


Here is the function that initializes fooMatrix:

Code: Select all
typedef Matrix<float, 4, 4> Mat4;

template<typename T, unsigned int rows, unsigned int cols>
Matrix<T, rows, cols>::Matrix(T *set)
{
    this->matrixData = new T*[rows];

    for (unsigned int i = 0; i < rows; i++)
    {
        this->matrixData[i] = new T[cols];
    }
   
    for (unsigned int i = 0; i < rows; i++)
    {
        for (unsigned int j = 0; j < cols; j++)
        {
            this->matrixData[i][j] = set[j * rows + i];
            counter++;
        }
    }
 }


This isn't just an output problem. I actually have to use the value of the matrix elsewhere, and it's value aligns with the described behaviours (whether or not I print it).
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby phlip » Thu May 31, 2012 12:00 am UTC

Without looking at any of the actual code, based on your description I'm going to say dangling pointer. That's usually the culprit when you have variables changing randomly without any apparent cause, and adding more statements that should be idempotent makes it behave differently.

Make sure you're not keeping a pointer to an object you've deleted, or which is allocated on the stack after that stack frame ends.

[edit]
OK, after looking at your initialisation code... I'm guessing Matrix also has a destructor, which deletes those arrays you're creating, but you haven't created a copy-constructor or an operator= that behave correctly? In which case that will cause a dangling pointer, like so:
Code: Select all
Matrix *a = new Matrix(some numbers);
Matrix *b = new Matrix(a); // invokes automatic copy-constructor - performs a shallow copy of all elements, so both a->matrixData and b->matrixData will point to the same array
delete a; // invokes destructor, deleting the array
doSomethingWith(b->matrixData); // this is a dangling pointer
delete b; // will attempt to double-free the matrixData array
This will also apply with your container:
Code: Select all
{
  Matrix a; // creates an array
  matricies.push(a); // invokes automatic copy-assignment operator, performs a shallow copy of all elements into the matrix object inside the container, matricies[n]->matrixData and a->matrixData will point to the same array
} // a goes out of scope, invokes destructor, matricies[n]->matrixData is now a dangling pointer

See also the rule of three. If you make a custom implementation of:
Code: Select all
Matrix::~Matrix();
Matrix::Matrix (const Matrix &);
Matrix & Matrix::operator= (const Matrix &);
then you usually need to have all three.
While no one overhear you quickly tell me not cow cow.
but how about watch phone?
User avatar
phlip
Restorer of Worlds
 
Posts: 6779
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Thu May 31, 2012 12:05 am UTC

I have, in fact, obeyed the rule of three. But let's say it is a pointer problem. Why would it change the printed value after I printed the value? For example, the following code:

Code: Select all
int *a = new int(3);
std::cout << a << std::endl;
*a = 4;

should output the same thing as this code:
Code: Select all
int *a = new int(3);
std::cout << a << std::endl;


My copy constructor and assignment operator all do deep copies of matrixData.

What's also interesting is that the matrix is the wrong value if I don't include the retrocausal lines, but the right value if I do.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Thu May 31, 2012 1:23 am UTC

What compiler and optimization level?
EvanED
 
Posts: 3781
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Thu May 31, 2012 1:34 am UTC

MinGW's G++, 0.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Thu May 31, 2012 1:48 am UTC

Have fun. :?

Personally I'd get it compiling on Linux (probably not to difficult since you're already building with GCC, unless you're deliberately using Windows-only stuff) and Valgrind it.
EvanED
 
Posts: 3781
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Thu May 31, 2012 1:52 am UTC

I am deliberately not using Windows only stuff because I want the engine to be cross platform. I'd prefer not to have to set up GLFW on my Linux partition, but it's not that much of a schlep I guess.

EDIT: The problem doesn't exist on Linux.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Thu May 31, 2012 3:10 am UTC

Did you just run it or did you Valgrind it? Because you should Valgrind it. It's (usually) easy and it will do a reasonable job at telling you if you have a latent memory error.
EvanED
 
Posts: 3781
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Thu May 31, 2012 3:12 am UTC

I just ran it. I don't have a problem on Linux, why would I Valgrind it?
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Thu May 31, 2012 3:17 am UTC

That's what I mean by "latent" memory errors. I.e. it's working correctly for the wrong reason, despite having a memory bug.
EvanED
 
Posts: 3781
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Thu May 31, 2012 3:27 am UTC

Well I don't see anything related to my problem. What do I do about "invalid read of size [n]"?
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Thu May 31, 2012 4:36 am UTC

Technically false positives can arise (remember the Debian SSH key generation bug that was sitting around for a few years? that was caused when someone tried to fix some benign Valgrind warnings and... overcorrected), but I've never seen a Valgrind message that didn't indicate a real problem (or at least a real potential problem). I strongly urge you to fix things until you get a clean run.

Invalid reads can be caused by (surprise surprise!) dangling pointers among other errors, like out-of-bounds arrays and just wild, uninitialized pointers.
EvanED
 
Posts: 3781
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Thu May 31, 2012 6:20 am UTC

It's happening when I'm calling a standard library function with a parameter that is not a pointer or a reference, and which contains neither pointers nor references. And also that happens far after the bug I was talking about. That's kind of confusing :|

Great, and now I can't even test it because Ubuntu's updating is screwing with my video card drivers.

EDIT: Just got worse than that. Ubuntu decided to crash during an update and now I can't even boot it up. I'm going to have to end up reinstalling ubuntu on that partition, and until then I can't use valgrind.

FURTHER EDIT: Good news, everyone! The program now works on Windows. I don't know what I did (and I didn't alter any of the code involving the matrices), but for whatever reason it now works. I'll be hypervigilant for using undefined behaviours and pointer screwups and such that cause unpredictable behaviour.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Thu May 31, 2012 4:23 pm UTC

sourmìlk wrote:It's happening when I'm calling a standard library function with a parameter that is not a pointer or a reference, and which contains neither pointers nor references. And also that happens far after the bug I was talking about. That's kind of confusing :|

...
FURTHER EDIT: Good news, everyone! The program now works on Windows. I don't know what I did (and I didn't alter any of the code involving the matrices), but for whatever reason it now works. I'll be hypervigilant for using undefined behaviours and pointer screwups and such that cause unpredictable behaviour.

Hmm. I guess that's good? Kinda?

What was the function you were calling?
EvanED
 
Posts: 3781
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Thu May 31, 2012 11:22 pm UTC

std::vector<Vec3>::push_back(Vec3); Now that I think about it, my Vector class (not the std::vector class) has an array that I may have forgotten to deep copy >.>

But it still happens far enough after the bug (and doesn't effect it if I run the code or not) that it wasn't the problem.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby phlip » Fri Jun 01, 2012 12:42 am UTC

sourmìlk wrote:FURTHER EDIT: Good news, everyone! The program now works on Windows. I don't know what I did (and I didn't alter any of the code involving the matrices), but for whatever reason it now works. I'll be hypervigilant for using undefined behaviours and pointer screwups and such that cause unpredictable behaviour.

:-/ Beware the bug which fixes itself... especially when it's one that you already know is highly dependent on random outside interference... It's entirely likely that it's not actually fixed, it's just working by chance now...
While no one overhear you quickly tell me not cow cow.
but how about watch phone?
User avatar
phlip
Restorer of Worlds
 
Posts: 6779
Joined: Sat Sep 23, 2006 3:56 am UTC
Location: Australia

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Fri Jun 01, 2012 3:18 am UTC

The only thing worse than a random, unrepeatable crash is a repeatable crash that goes away when you change something completely unrelated, and you cannot figure out how to get it back.

Almost certainly the flaw in your program is still there.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.
User avatar
Yakk
 
Posts: 10064
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Fri Jun 01, 2012 4:12 am UTC

Yeah, well that's why I said I was being hypervigilant. I know that bugs that fix themselves are often just hiding. But for now that's good enough!
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Fri Jun 01, 2012 3:27 pm UTC

I can think of one possibility. What are you using as a build system?

Is it possible that things stopped working when you changed a couple files and one of them wasn't rebuilt? And started working when it was? This sort of thing can easily happen with 'make' if you change a header but that header isn't listed as a dependency of some source file that includes it. (Getting all this crap to work right is a big part of why I use scons instead.)

I'm still not seeing a bigger picture in terms of how this all fits together to give you these symptoms, but it would help explain why it went away and why adding code after broke things.
EvanED
 
Posts: 3781
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Fri Jun 01, 2012 9:30 pm UTC

I cleaned the project several times, so it should have been rebuilding all the necessary things. I'm going with the theory that quantum randomness caused a few particles to behave retrocausally in an extreme consistent way until I rebooted my computer. When it doubt, blame it on quantum.
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby Ben-oni » Sat Jun 02, 2012 1:54 am UTC

I notice that you're using templates.

Code: Select all
#include <iostream>

using namespace std;

int idCount = 0;

int getID() {
   return idCount++;
}

template<int>
class C {
public:
   static int id;
};

template<int n>
int C<n>::id = getID();

int main(int argc, char** argv) {
   C<0> x;
   cout << "x.id = " << x.id << endl;
   cout << "There are " << idCount << " template classes used throughout this program." << endl;
   C<1> y;
   cout << "y.id = " << y.id << endl;
   return 0;
}


If you add to the end of main another statement, say, "cout << C<2>::id << endl", the number given before changes!

So, yes. It's quite possible for code that occurs later to effect a retrocausal change.
Last edited by Ben-oni on Sat Jun 02, 2012 5:56 am UTC, edited 1 time in total.
Ben-oni
 
Posts: 270
Joined: Mon Sep 26, 2011 4:56 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Sat Jun 02, 2012 4:24 am UTC

Is it incrementing idCount at compile time? That's pretty cool. It may explain the bug, now that I think about it (though I don't think it does).
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby EvanED » Sat Jun 02, 2012 4:27 am UTC

sourmìlk wrote:Is it incrementing idCount at compile time? That's pretty cool. It may explain the bug, now that I think about it (though I don't think it does).

It is, at compile time, inserting code that will call getID() one additional time (during global initialization). The actual increments still happen at runtime.

It's like the difference between
Code: Select all
int getID() { /* same as before */ }
int x1 = getID();

and
Code: Select all
int getID() { /* same as before */ }
int x1 = getID();
int x2 = getID();

except that the x1 and x2 are being done via template machinery.

But I agree that that seems like an... unlikely cause. Especially given the other symptoms (changing behavior on Linux and under a debugger).
EvanED
 
Posts: 3781
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI

Re: The "IT DOESN'T WORK!" thread

Postby sourmìlk » Sat Jun 02, 2012 4:40 am UTC

That's still a cool thing to know. I remember reading an article on really subtle ways to make your code unmaintainable. I feel like that's a technique that could be employed >:)
Terry Pratchett wrote:The trouble with having an open mind, of course, is that people will insist on coming along and trying to put things in it.
User avatar
sourmìlk
If I can't complain, can I at least express my fear?
 
Posts: 6405
Joined: Mon Dec 22, 2008 10:53 pm UTC
Location: permanently in the wrong

Re: The "IT DOESN'T WORK!" thread

Postby ahammel » Sun Jun 03, 2012 8:30 pm UTC

Riddle me this, Batman:

I'm just learning C, so I'm fooling around with some basic stuff. I've got a Seive or Eratosthenes program that works perfectly for seemingly any input other than 50. Observe:

Code: Select all
$ echo 51  | ./seive
   2
  ... [other primes ommitted]
  47

$ echo 49 | ./seive
   2
  ...
   47


$ echo 50 | ./seive
   2
  ...
   47
*** glibc detected *** ./seive: double free or corruption (out): 0x0000000001bfa010 ***
seive: malloc.c:2451: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
zsh: done       echo 50 |
zsh: abort      ./seive


Source:
Code: Select all
#include <stdio.h>
#include <stdlib.h>

int *seive(int max) {
    int i, j;
    int *a = malloc (sizeof(int) * max);
    for (a[1] = 0, i = 2; i <= max; i++) {
        a[i] = 1;
    }
    for (i = 2; i <= max/2; i++) {
        if (a[i]) {
            for (j = 2; j <= max/i; j++) {
                a[i*j] = 0;
            }
        }
    }
    return a;
}

int main() {
    int i;
    int primes_to;
    scanf("%d", &primes_to);
    int *seive_array = seive(primes_to);
    for (i = 1; i <= primes_to; i++) {
        if (seive_array[i]) {
            printf("%4d\n", i);
        }
    }
    free(seive_array);
    return EXIT_SUCCESS;
}
I also answer to 'Alex'
User avatar
ahammel
 
Posts: 978
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC

Re: The "IT DOESN'T WORK!" thread

Postby jaap » Sun Jun 03, 2012 9:27 pm UTC

In C (and C++) arrays are indexed starting from zero. Therefore
ahammel wrote:
Code: Select all
    int *a = malloc (sizeof(int) * max);

allocates space for the array elements a[0] up to a[max-1].
You actually write/read to a[max], so you are overshooting the end of the array, corrupting memory, and so anything can happen.
The simplest fix is to use
Code: Select all
    int *a = malloc (sizeof(int) * (max+1));


By the way, it is "sieve", not "seive".
Also, you can rewrite your inner loop so that it does not use multiplication or division, which may make it a bit faster.
User avatar
jaap
 
Posts: 1731
Joined: Fri Jul 06, 2007 7:06 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby ahammel » Sun Jun 03, 2012 11:28 pm UTC

Well I feel silly. I don't know why I didn't think of an array overflow before. And I spelled the function wrong. Not a good day.

Thanks for your help!
I also answer to 'Alex'
User avatar
ahammel
 
Posts: 978
Joined: Mon Jan 30, 2012 12:46 am UTC
Location: Vancouver BC

Re: The "IT DOESN'T WORK!" thread

Postby Robert'); DROP TABLE *; » Thu Jun 21, 2012 12:02 am UTC

I hate working with raw bytestreams. Trying to read an image produces a block of data that 8 bytes too long for the space it's supposed to fill, and then when I fix the apparent bug, it ends up 20 bytes too short. Then when I rebuild the logic, it's 50 bytes too long. :?

(There might be an example later. I'm currently on a different machine than my code.)
...And that is how we know the Earth to be banana-shaped.
User avatar
Robert'); DROP TABLE *;
 
Posts: 635
Joined: Mon Sep 08, 2008 6:46 pm UTC
Location: in ur fieldz

Re: The "IT DOESN'T WORK!" thread

Postby pedros » Thu Jun 21, 2012 4:37 pm UTC

http://www.phpprobid.com/

a horrendous mess of disjointed php and table based layouts. and the support is nonexistent. and (although i don't know how much my new employers paid for it) they have the cheek to charge for it.

shopping carts which allow you to sell more of a thing than you have == doesn't work
pedros
 
Posts: 3
Joined: Mon Mar 07, 2011 11:16 pm UTC

Re: The "IT DOESN'T WORK!" thread

Postby BRNMan » Tue Jun 26, 2012 5:40 pm UTC

So I'm programming an app in C# to get a random xkcd comic and display it on my desktop. It can display .jpg images, like the ones used in earlier comics, but it can't display .png images even after it should be converted. I'm using Windows 7 as my OS. Here's a code sample:

Code: Select all
Class Program
{
Program()
{
WebClient wc = new WebClient();
String comicDirectory = Directory.GetCurrentDirectory();
String comicFromWebDir = Directory.GetCurrentDirectory() + "\\comic.bmp";
//...
//parse json and extract comic url
//...
File.SetAttributes(comicDirectory, FileAttributes.Normal);//to prevent Unauthorized Access Exception
wc.DownloadFile(imgURI, comicFromWebDir);//download file with WebClient
Wallpaper.SetDesktopWallpaper(WallPaperType.Fit, comicFromWebDir);
File.Delete(comicFromWebDir);
}
static void Main(string[] args)
{
Program pg = new Program();
}
}


Here's the code for wallpaper. This is the whole class.

Code: Select all
public static class Wallpaper
    {
        public static bool SupportFitFillWallpaperStyles
        {
            get
            {
                return (Environment.OSVersion.Version >= new Version(6, 1));
            }
        }

        public static void SetDesktopWallpaper(WallPaperType style, string path)
        {
            RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
            switch (style)
            {
                case WallPaperType.Tiled:
                    key.SetValue(@"WallpaperStyle", "0");
                    key.SetValue(@"TileWallpaper", "1");
                    break;
                case WallPaperType.Center:
                    key.SetValue(@"WallpaperStyle", "0");
                    key.SetValue(@"TileWallpaper", "0");
                    break;
                case WallPaperType.Stretch:
                    key.SetValue(@"WallpaperStyle", "2");
                    key.SetValue(@"TileWallpaper", "0");
                    break;
                case WallPaperType.Fit: //Windows 7 and later
                    if (!SupportFitFillWallpaperStyles)
                        goto case WallPaperType.Stretch;
                    key.SetValue(@"WallpaperStyle", "6");
                    key.SetValue(@"TileWallpaper", "0");
                    break;
                case WallPaperType.Fill: //Windows 7 and later
                    if (!SupportFitFillWallpaperStyles)
                        goto case WallPaperType.Stretch;
                    key.SetValue(@"WallpaperStyle", "10");
                    key.SetValue(@"TileWallpaper", "0");
                    break;
            }
            key.Close();
           
            SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, path, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
            SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, path, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);//2x just to make sure
        }

        private const uint SPI_SETDESKWALLPAPER = 20;
        private const uint SPIF_UPDATEINIFILE = 0x01;
        private const uint SPIF_SENDWININICHANGE = 0x02;

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SystemParametersInfo(uint uiAction, uint uiParam, string pvParam, uint fWinIni);
    }

    public enum WallPaperType
    {
        Tiled,
        Center,
        Stretch,
        Fit,
        Fill,
    }
}


Thank you!
User avatar
BRNMan
 
Posts: 32
Joined: Tue May 22, 2012 10:29 am UTC

Re: The "IT DOESN'T WORK!" thread

Postby Yakk » Wed Jun 27, 2012 1:47 am UTC

Have you tried converting the png to a jpg file, saving it out, and manually setting it as a desktop wallpaper?

Speaking of which, why do you think you'd be converting that file? It looks (to me) that you are just saving the file with a .bmp extension, not doing any conversion.
One of the painful things about our time is that those who feel certainty are stupid, and those with any imagination and understanding are filled with doubt and indecision - BR

Last edited by JHVH on Fri Oct 23, 4004 BCE 6:17 pm, edited 6 times in total.
User avatar
Yakk
 
Posts: 10064
Joined: Sat Jan 27, 2007 7:27 pm UTC
Location: E pur si muove

Re: The "IT DOESN'T WORK!" thread

Postby BRNMan » Wed Jun 27, 2012 2:38 pm UTC

Yakk wrote:Have you tried converting the png to a jpg file, saving it out, and manually setting it as a desktop wallpaper?

Speaking of which, why do you think you'd be converting that file? It looks (to me) that you are just saving the file with a .bmp extension, not doing any conversion.


I guess I can blame google for that. I tried to find out how to save it as a bitmap and someone wrote that all you had to do was change the extension. Naturally gullible, that's exactly what I did! I fixed it, thanks for your help!
User avatar
BRNMan
 
Posts: 32
Joined: Tue May 22, 2012 10:29 am UTC

PreviousNext

Return to Coding

Who is online

Users browsing this forum: No registered users and 9 guests