si8 buffer[size];
What happens if you malloc this buffer?
Other than that, check that inputs are sane, the problem might be elsewhere.
si8 buffer[size];
Quote:Original post by Ectara
But, my question was, does anyone have a method of preventing a variable from being optimized out other than declaring it volatile? I know where the problem lies, just looking for an alternate solution.
void E_errorSetErrorStr(const si8 * message){ si32 tlock = E_globalErrorLock; while(tlock) /* Compiler might make this always true, and infinite loop, or always false, and cause serious problems. */ tlock = E_globalErrorLock; E_globalErrorLock = 1; while(E_globalErrorCount>=E_ERROR_MAX_ERRORS){ E_error *terror = NULL; if(E_globalErrorCount>2) terror = E_globalError.next->next; if(E_globalErrorCount>=2){ strncpy(E_globalError.error,E_globalError.next->error,E_ERROR_BUFLEN); E_globalError.code = E_globalError.next->code; free(E_globalError.next); } if(E_globalErrorCount==1) memset(&E_globalError,0,sizeof(E_error)); else E_globalError.next = terror; --E_globalErrorCount; } E_error *terror = &E_globalError; if(E_globalErrorCount){ while(terror->next) terror = terror->next; terror->next = (E_error*)malloc(sizeof(E_error)); if(E_errorGetAllocError(terror->next,E_TEST_CACHE))return; terror = terror->next; } strncpy(terror->error,message,E_ERROR_BUFLEN);#ifdef E_ERROR_DEBUG fprintf(stderr,"%s\n",message);#endif terror->code = 0; terror->next = NULL; ++E_globalErrorCount; E_globalErrorLock = 0; return;}
si32 tlock = E_globalErrorLock; while(tlock) tlock = E_globalErrorLock; E_globalErrorLock = 1;
Quote:Original post by PlayerX
Maybe GCC is similar to Visual-C in that you need to specify if your program is to run in a multi-threaded environment. Your compiler may be assuming your code is singly-threaded and therefore safe to optimise away that E_globalErrorLock check. With VC there is the -MT flag to tell the compiler to assume globals can be changed by other threads and not to make those sorts of assumptions. Perhaps GCC has a similar flag.
Also, in a multi-threaded environment, this code will cause issues:si32 tlock = E_globalErrorLock; while(tlock) tlock = E_globalErrorLock; E_globalErrorLock = 1;
The problem is the thread could be switched away from between reading E_globalErrorLock into tlock and checking the contents of tlock. eg. say E_globalErrorLock is zero when you enter this code. The first line is run loading E_globalErrorLock into tlock, which is zero. Your thread gets switched away to another one that also runs this code. The new thread runs through all three lines, setting E_globalErrorLock to one, and starts to run the code afterwards, then it too is switched away. The original thread runs, sees tlock is zero and sets E_globalErrorLock to one (when it is already one) and runs the same code. You now have two threads running the code you only wanted one thread to use.
You ideally should be using the platform-specific atomic test-and-set functions for things like this. They're guaranteed to operate correctly in a multi-threaded, multi-CPU environment.
si32 tlock = E_globalErrorLock;while(tlock) tlock = E_globalErrorLock;E_globalErrorLock = 1;
Quote:Original post by Ravyne
I can honestly say I've used maybe two globals in anything I've written in the last 4 years, most of which are smallish, but non-trivial programs between 5k and 25k lines of code.