Thread: Why does this cause an error?

  1. #1
    Registered User
    Join Date
    Nov 2006
    Posts
    184

    Why does this cause an error?

    Code:
    void testTLS()
    {
        ...elided...
        Test* t;
    
         if ( !( t = ( Test* ) TlsGetValue( index )  )
         {
              t = new Test();
              TlsSetValue( index, t );
         }
    
         ...elided...
    
         //This cause the error
         delete t; //If I remove this, it works properly
    }

  2. #2
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    What kind of error?

    Post the smallest piece of compilable code that exhibits the problem. It's hard to tell when you've elided parts of the code.

  3. #3
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    Perhaps because the logic path taken did not include the call to "new".
    Mainframe assembler programmer by trade. C coder when I can.

  4. #4
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by Todd Burch View Post
    Perhaps because the logic path taken did not include the call to "new".
    Or maybe t is getting deleted twice. It's hard to tell.

  5. #5
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by Todd Burch View Post
    Perhaps because the logic path taken did not include the call to "new".
    No, I created a boolean wasntSet, to test that and then only delete if "new" was called (and that's only called once) and it throws an error. the error is one of those "send report to microsoft" errors.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    The "send this to microsoft" is simply a response to an access violation. If you call the function you posted [assuming it's not got any "funny" stuff in the ... elided ... sections], you will delete t every time you enter the function. I'm pretty sure you should not delete this element until you have decided to not use the TLS element (remember, TLS only stores a pointer to your object, so if you delete it in the midst of using TLS, it will "disappear" before you've finished with it.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> if ( !( t = ( Test* ) TlsGetValue( index ) )

    Don't type up psuedo-code of what you think the code is doing - copy/paste - remove anything you think doesn't apply. But even then, you may remove the code that's cuasing the problem.

    Write up a very simple console app that demonstrates the problem. Post that so others can compile and debug if need be.

    gg

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'm in a kind mood today, so I'm posting some TLS code that works:
    Code:
    #include <iostream>
    #include <sstream>
    #include <process.h>
    #include <windows.h>
    
    volatile int threadCount = 0;
    int index = -1;
    typedef int TLSData;
    
    TLSData *getTls(void)
    {
    	return (TLSData *)TlsGetValue(index);
    }
    
    TLSData *makeTls(int content)
    {
    	TLSData *p = new TLSData;
    	*p = content;
    	TlsSetValue(index, p);
    	return p;
    }
    
    void destroyTls(void)
    {
    	TLSData *p = getTls();
    	delete p;
    }
    
    
    void threadfunc(void *ap)
    {
    	int threadId = *(int *)ap;
    	TLSData *t;
    	for(int i = 0; i < 100; i++)
    	{
    		std::stringstream ss;
    		if ((t = getTls()) == NULL)
    			t = makeTls(threadId);
    		ss << "Thread " << *t << std::endl;
    		std::cout << ss.str();
            Sleep(500);
    	}
    	destroyTls();
    	threadCount--;
    }
    
    
    
    int main()
    {
    	index = TlsAlloc();
    	if (index == TLS_OUT_OF_INDEXES)
    	{
    		std::cout << "Error, out of TLS indexes" << std::endl;
    		return 1;	
    	}
    	for(int i = 0; i < 6; i++)
    	{
    		_beginthread(threadfunc, 0, &i);
    		threadCount++;
    		Sleep(1500);
    	}
    	while(threadCount > 0)
    		Sleep(1000);
    	TlsFree(index);
    	return 0;
    }
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    (nasty v-keyword)
    Some minor improvements to matsp code
    Code:
    #include <iostream>
    #include <sstream>
    #include <process.h>
    #include <windows.h>
    
    #if _MSC_VER >= 1400 
    volatile int threadCount = 0;
    #else
    #error "Compiler not supported" 
    #endif
    int index = -1;
    typedef int TLSData;
    
    TLSData *getTls()
    {
        return (TLSData *)TlsGetValue(index);
    }
    
    TLSData *makeTls(int content)
    {
        TLSData *p = new TLSData;
        *p = content;
        TlsSetValue(index, p);
        return p;
    }
    
    void destroyTls()
    {
        TLSData *p = getTls();
        delete p;
    }
    
    
    void threadfunc(void *ap)
    {
        int threadId = (int)ap;
        TLSData *t;
        for(int i = 0; i < 5; i++)
        {
            std::stringstream ss;
            if ((t = getTls()) == NULL)
                t = makeTls(threadId);
            ss << "Thread " << *t << std::endl;
            std::cout << ss.str();
            Sleep(500);
        }
        destroyTls();
        threadCount--;
    }
    
    int main()
    {
        index = TlsAlloc();
        if (index == TLS_OUT_OF_INDEXES)
        {
            std::cout << "Error, out of TLS indexes" << std::endl;
            return 1;	
        }
        for(int i = 0; i < 6; i++)
        {
            _beginthread(threadfunc, 0, (void*)i);
            threadCount++;
            //Sleep(1500);
        }
        while(threadCount > 0)
            Sleep(1000);
        TlsFree(index);
        return 0;
    }
    gg

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    So, I presume volatile is no longer supported by the new compiler because it always makes globals volatile??? (Or is that version 1.4, not version 14 - my compiler certainly accepts the code, and it's using VC 7.0)

    The sleep 1500 in main is to make the subsequent threads start later - otherwise it's hard to tell which thread is actually running when - it obviously serves no purpose to anything else.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> I presume volatile is no longer supported ...
    I think you're looking at it backwards...
    Code:
    #if _MSC_VER >= 1400 
    volatile int threadCount = 0;
    #else
    #error "Compiler not supported" 
    #endif
    Microsoft added multi-threaded semantics to volatile starting at version 14.0.0 (VC++ 2005). The "semantics" being "interlocked-style" access to volatile variables. Using volatile in this fashion on any other compiler is incorrect.
    http://cboard.cprogramming.com/showt...687#post701687

    >> it obviously serves no purpose to anything else
    Since you're passing the address of i, I assumed the sleep was to allow enough time for the thread to dereference it. It's not a good way to communicate i to the threads.

    gg

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Codeplug View Post
    >> I presume volatile is no longer supported ...
    I think you're looking at it backwards...
    Code:
    #if _MSC_VER >= 1400 
    volatile int threadCount = 0;
    #else
    #error "Compiler not supported" 
    #endif
    Microsoft added multi-threaded semantics to volatile starting at version 14.0.0 (VC++ 2005). The "semantics" being "interlocked-style" access to volatile variables. Using volatile in this fashion on any other compiler is incorrect.
    http://cboard.cprogramming.com/showt...687#post701687
    Ok, but the way that the variables are used in the code I wrote is sufficiently simple that reloading them will work. But I'm sure there are better ways to know if all the threads have finished - I just didn't want to spend the time searching for those ways - I don't do Windows thread programming every day... The purpose of my code was to show how to use TLS, and as far as I can see, you haven't changed that.

    >> it obviously serves no purpose to anything else
    Since you're passing the address of i, I assumed the sleep was to allow enough time for the thread to dereference it. It's not a good way to communicate i to the threads.

    gg
    That is indeed a good point, although it was not actually my intention.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. An error is driving me nuts!
    By ulillillia in forum C Programming
    Replies: 5
    Last Post: 04-04-2009, 09:15 PM
  3. Making C DLL using MSVC++ 2005
    By chico1st in forum C Programming
    Replies: 26
    Last Post: 05-28-2008, 01:17 PM
  4. Connecting to a mysql server and querying problem
    By Diod in forum C++ Programming
    Replies: 8
    Last Post: 02-13-2006, 10:33 AM
  5. Couple C questions :)
    By Divx in forum C Programming
    Replies: 5
    Last Post: 01-28-2003, 01:10 AM