tags:

views:

268

answers:

8

I have some really weird crash here, ive got it before, but i thought i fixed it by adding = NULL to the variable declarations:

#include <stdlib.h>

...

GLuint *TEX = NULL;
int TEX_MEMSIZE = sizeof(GLuint)*1024*1024;

...

void something1(){
    ...
    TEX = (GLuint *)malloc(TEX_MEMSIZE);
    ...
}

void something2(){
    ...
    // this line runs fine.
    if(TEX != NULL){ // CRASH ON THIS LINE OF CODE
        // wont run anything after the above line.
        free(TEX);
    }
    // ...nor here since it crashed...
    ...
}

It crashes on my laptop/vista, but not on my desktop computer/winXP.

When i remove that if check and the free(), it wont crash anymore.

I just dont get it, what im doing wrong? What could cause this? i only know incorrectly predefined arrays can cause some illogical errors, i dont believe there is such incorrect arrays in my code now, so im waiting for more ideas. (and because checking 20k lines of codes can be quite slow too)

Edit: Now i noticed it will not crash before free() but AFTER it. I start thinking its some predefined array problem... since the position of crash is changing. (or i just have dementia).

EDIT 2: FIXED, there was two free() calls, before and after malloc() >_> i feel so stupid now.

+1  A: 

How is TEX_MEMSIZE defined?

It should be something like:

#define NUM_ENTRIES 50
#define TEX_MEMSIZE NUM_ENTRIES * sizeof(GLuint)
vicatcu
Even if he's allocated the wrong size, I wouldn't expect the line he points at to crash. There must be some code that was omitted from the snippet that does something weird.
asveikau
i added the TEX_MEMSIZE declaration now.
@Newbie, I would spend a little time reading about debugging with GDB, set some breakpoints and start stepping through your code. The likely thing is that you are crashing because you are trying to free a pointer that has previously been free'd.
vicatcu
holy shit you are right, i had free() before and after malloc >_> hmm should i accept this post, even though the correct answer is in your comment of your answer? ;/
A: 

From the given data, and assuming that the program is multi-threaded, there might be a race condition between the if (TEX != NULL) check and the free, which might result in a free on a NULL pointer. You might want to check that out.

sudar
hmm... i wish i knew how to make multi-threaded programs :)
Then the case might be that TEX now points to a memory location that has not been malloc()ed, that way it wont be NULL, but will result in a free() on unallocated memory.
sudar
how could that be possible my winXP doesnt crash on that then? the program runs just fine with my winXP, and i checked that TEX is malloced only in one place of the code (and nowhere else is even TEX = anything)
For one thing, memory corruption can be pretty complex to figure out just by looking at code. High time you consider a debugger.
sudar
MSVC++ is what i use, i think there is debugger, since it says every time i compile "debug information not found, do you want to continue debugging?" and when i press "yes" it will run the program and crash it million times and then it shows some machine code/ASM, i dont really understand how i can debug with ASM codes.. i know pretty much nothing about ASM so its kinda useless for me. I dont really know how to even use this MSVC++ i wish someone told me the MUST-KNOW things i must know when developing... -_-
I'm not a windows programmer, but people here might be able to point you to windows source level debuggers which wont need you to look at ASM. But yes, its good to know asm to debug binaries where no debug info is available.
sudar
A: 

Hi,

Assuming that TEX is truely a pointer type (meaning you don't have it re-declared at a more local scope), The only way the line

if(TEX != NULL){

Could cause a crash is if accessing TEX caused an invalid memory access. Since TEX is a global variable, the only way it could be at invalid memory is if the DLL that defines TEX is not loaded into the process. Put a breakpoint before the IF statement and verify that the DLL that contains the TEX declaration is loaded into the process.

Of course, if you did have a debugger, you probably would have told us what the unhandled exception type was. If you don't have access to a debugger, then put a

sleep (60 * 1000 * X);

before the IF statement and use the Windows Internals' "Process Explorer" utility (now distributed by Microsoft) to see what modules are loaded in the process. Set 'X' to the number of minutes it'll take you to do this, 2 or 3 should be sufficient.

David Gladfelter
A: 

repeat the same TEX != NULL test all over the place, it will surely be OK right after the malloc; its certainly broken later on.

Keep repeating the test in all the '...' code. Eventually you find that there is a place where it worked before line x but not after it. THis will point the finger at the problem

Or your debug symbols are wrong and the crash is not happening where you think it is. Close VS, reopen, rebuild all and try again

pm100
ive opened VS many times, and it always does the same debug symbol error.
A: 

My crystal ball says the you need to do

#include <stdlib.h>

in all the source files where you use malloc(), realloc() and free(). If that doesn't solve your problem, then you have to post a minimum compilable code that exhibits the behavior.

If that does solve your problem: a missing #include <stdlib.h> means that malloc() has no prototype in scope. The compiler assumes that it returns int. It doesn't, of course. Normally, the compiler would have warned you when you assign the result of malloc() to a pointer type, but because of the cast, the compiler assumes you know what you're doing and doesn't warn you. For this reason, I don't recommend casting the return value of malloc() in C.

So, your malloc() call would be:

#include <stdlib.h>
TEX = malloc(TEX_MEMSIZE);

Also, you're assuming that sizeof(int) divides TEX_MEMSIZE. Do you want TEX_MEMSIZE bytes, or TEX_MEMSIZE ints? If latter, you need to multiply by sizeof(int) in your malloc() call:

TEX = malloc(TEX_MEMSIZE * sizeof *TEX);

You should also change the type of TEX_MEMSIZE. In C, int is only guaranteed to store values <= 32767. It may be able to store larger values, but that is not certain. Since you use it for malloc(), I would recommend size_t type, or better yet, make it a #define.

Based upon your edit, it could be that you're changing TEX after malloc(), and then passing that value to free(). Are you sure TEX isn't changed between malloc() and free()?

Alok
i have that line ofc. edited my post now. if that was the problem, how my program could work with my winXP but not on my vista?
@Newbie, see my edit. Maybe that will help.
Alok
@Newbie: also, not having `#include <stdlib.h>` can definitely result in working in XP but not in Vista, or vice-versa, or whatever. For one, maybe in XP the size of a pointer is the same as the size of int, but not so in Vista.
Alok
"int is only guaranteed to store values <= 32767" erm? int stores up to 4 billion values, not 32767... that is short int datatype. And im using unsigned int in my TEX data. i dont see how this problem can be caused by a different names for the same things... sizeof(unsigned int) = sizeof(GLuint) = sizeof(size_t) Yes im sure i dont change the TEX pointer value except when i malloc it.
@Newbie: on your system. But in general, `int` is only guaranteed a range of [-32767,32767]. It could be higher, as in your case. `sizeof(unsigned int)` may or may not be equal to `sizeof(size_t)`. But to answer your problem, you are corrupting your program's memory somewhere. I would recommend compiling with warnings enabled, and removing `malloc()` casts as a start.
Alok
you blow my mind man... so i can trust nothing then... what takes 4 bytes can take 2 bytes, thats just fucked up... doesnt make sense, why would those change when i compile my program only at one computer? yeah any suggestions for malloc() that doesnt lose performance a tiny bit at all...?
Well, on a given system, with a given compiler, the sizes shouldn't change, but it is a bad idea to depend upon absolute sizes of different data types (except for char, [u]int*_t, etc.). My suggestion for malloc doesn't lose any performance: it helps in finding bugs though. See http://stackoverflow.com/questions/1868719/sigsegv-seemingly-caused-by-printf/1871102#1871102 for example.
Alok
i referred to "and removing malloc() casts as a start" when talked about performance
Yes, and it won't hurt performance. It is the right thing to do anyway.
Alok
oh okay, ill do what you say, though isnt it clearer to put TEX_MEMSIZE = 1024*1024 * sizeof(*TEX); ? also notice the () around *TEX...
I think it's clearer to have the `sizeof *TEX` in `malloc()`, but if `TEX_MEMSIZE` is only going to be used for this purpose, and if `TEX` is visible when you define `TEX_MEMSIZE`, you could do it your way too. Good luck finding the bug, I will be interested in knowing what it was when you find it.
Alok
found it! look at edits
+2  A: 
free(TEX);

frees the memory, but doesn't change the pointer. Change it to

if (TEX != NULL)
{
    free(TEX);
    TEX = NULL;
}

So if you call something2() a second time, it won't try to free(TEX) again.

groovingandi
Offtopic - but there is no need to check for NULL when freeing - free() handles a NULL
Martin Beckett
really? i remember having problems without checking, maybe it was some other bug then and it magically fixed by that if check, idk. i tried TEX = NULL but it doesnt make difference...
@Newbie: `free(x)` frees `x`, but doesn't set `x` to `NULL`. So, calling `free()` on it again is bad. But if you did: `free(x); x = NULL; free(x);`, that is okay.
Alok
hmm... i wonder why it didnt fix the problem then o.o i think my program has ghosts in it.
A: 

Based on your update to the question, where the not the NULL check but instead the free() call crashes:

Something in your program is corrupting either the heap infrastructure or the actual value of TEX.

Darron
A: 

The problem is not the free itself. Your bug lies in the code not quoted in this post, as you must have overwritten memory above your allocated region. If you get a crash in free() it is mostly because of 2 things:

  • you passed a wrong pointer ( not allocated with malloc() )
  • you have overwritten memory before or after the block you allocated

I am pretty sure no. 2 will be your issue in this case.

DarthCoder