Thread: [Quickfix-developers] Confused by possible bug in Utility.cpp / thread_spawn
Brought to you by:
orenmnero
From: K. F. <kfr...@gm...> - 2013-01-10 17:36:28
|
Hello List! Background: I am trying to build QuickFIX with mingw-w64. To do this, I am starting with the windows "version" of the code, i.e.,the code paths that are active when _MSC_VER is defined. I am confused by what looks to me like a bug, but I probably don't understand it correctly. If the bug I'm imagining were actually present, it would seem that QuickFIX would neither compile nor run on windows. Specifically the function thread_spawn is defined in Utility.cpp. The function begins: bool thread_spawn( THREAD_START_ROUTINE func, void* var, thread_id& thread ) In the windows section is the line: result = _beginthreadex( NULL, 0, &func, var, 0, &id ); It appears to me that the '&' in "&func" is an error, and shouldn't be there. I reason as follows: THREAD_START_ROUTINE is a typedef in Utility.h. Its windows version is: typedef unsigned int (_stdcall THREAD_START_ROUTINE)(void *); I read this as a pointer to a function that takes a void* and returns an unsigned. Compare with the unix version: extern "C" { typedef void * (THREAD_START_ROUTINE)(void *); } which I also read as a pointer to a function, but now the function returns a void*. Because of the '&' in "&func", a pointer to a pointer to a function is being passed to _beginthreadex, rather than pointer to a function. (recall: result = _beginthreadex( NULL, 0, &func, var, 0, &id );) >From msdn, _beginthreadex has the prototype: uintptr_t _beginthreadex( void *security, unsigned stack_size, unsigned ( *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr ); which I read as _beginthreadex expecting a pointer to a function. Compare with the unix version. From Utility.cpp: if( pthread_create( &result, 0, func, var ) != 0 ) return false; Here there is no '&' on func, so pthread_create is being passed a pointer to a function (as expected). >From the pthreads documentation, pthread_create has the prototype: int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg); which I read as taking a pointer to a function that takes a void* and returns a void*. So it looks to me that the unix version is correct and there is no type mismatch in the function call to pthread_create, but in the windows version there is a type mismatch in the corresponding call to _beginthreadex, with a pointer-to-function being expected, but a pointer-to-pointer-to-function being passed, with the extra "pointer-to" coming from the '&' in "&func". Of course, the problem with my interpretation is that the windows version shouldn't compile, and if one were to shut the compiler up by casting away the type mismatch, the program should crash. My QuickFIX source is from quickfix-1.13.3.zip, downloaded on Jan. 2. (I have been tweaking the code to get it to build with mingw-w64, and after tweaking that doesn't change this part of the code, mingw-w64 does give the type-mismatch error described.) Any help understanding what is going on here would be appreciated. K. Frank |
From: K. F. <kfr...@gm...> - 2013-01-15 14:46:36
|
Hi List! Ping? On its face this looks like a bug in the QuickFIX code. I'm assuming quickfix-developers is the right place to raise such an issue. Is there a better place? Thanks. K. Frank On Thu, Jan 10, 2013 at 12:36 PM, K. Frank <kfr...@gm...> wrote: > Hello List! > > Background: I am trying to build QuickFIX with mingw-w64. To do this, > I am starting with the windows "version" of the code, i.e.,the code > paths that are active when _MSC_VER is defined. > > I am confused by what looks to me like a bug, but I probably don't > understand it correctly. If the bug I'm imagining were actually > present, it would seem that QuickFIX would neither compile nor > run on windows. > > Specifically the function thread_spawn is defined in Utility.cpp. > > The function begins: > > bool thread_spawn( THREAD_START_ROUTINE func, void* var, thread_id& thread ) > > In the windows section is the line: > > result = _beginthreadex( NULL, 0, &func, var, 0, &id ); > > It appears to me that the '&' in "&func" is an error, and shouldn't > be there. > > I reason as follows: > > THREAD_START_ROUTINE is a typedef in Utility.h. Its windows version is: > > typedef unsigned int (_stdcall THREAD_START_ROUTINE)(void *); > > I read this as a pointer to a function that takes a void* and returns > an unsigned. > > Compare with the unix version: > > extern "C" { typedef void * (THREAD_START_ROUTINE)(void *); } > > which I also read as a pointer to a function, but now the function > returns a void*. > > Because of the '&' in "&func", a pointer to a pointer to a function > is being passed to _beginthreadex, rather than pointer to a function. > (recall: result = _beginthreadex( NULL, 0, &func, var, 0, &id );) > > From msdn, _beginthreadex has the prototype: > > uintptr_t _beginthreadex( > void *security, > unsigned stack_size, > unsigned ( *start_address )( void * ), > void *arglist, > unsigned initflag, > unsigned *thrdaddr > ); > > which I read as _beginthreadex expecting a pointer to a function. > > Compare with the unix version. From Utility.cpp: > > if( pthread_create( &result, 0, func, var ) != 0 ) return false; > > Here there is no '&' on func, so pthread_create is being passed a > pointer to a function (as expected). > > From the pthreads documentation, pthread_create has the prototype: > > int pthread_create(pthread_t *thread, const pthread_attr_t *attr, > void *(*start_routine)(void*), void *arg); > > which I read as taking a pointer to a function that takes a void* > and returns a void*. > > So it looks to me that the unix version is correct and there is > no type mismatch in the function call to pthread_create, but in > the windows version there is a type mismatch in the corresponding > call to _beginthreadex, with a pointer-to-function being expected, > but a pointer-to-pointer-to-function being passed, with the extra > "pointer-to" coming from the '&' in "&func". > > Of course, the problem with my interpretation is that the windows > version shouldn't compile, and if one were to shut the compiler > up by casting away the type mismatch, the program should crash. > > My QuickFIX source is from quickfix-1.13.3.zip, downloaded on > Jan. 2. > > (I have been tweaking the code to get it to build with mingw-w64, > and after tweaking that doesn't change this part of the code, > mingw-w64 does give the type-mismatch error described.) > > > Any help understanding what is going on here would be appreciated. > > > K. Frank |
From: Mike G. <mg...@co...> - 2013-01-15 18:11:10
|
It works with the VS compiler (32-bit, anyway). Can you post the actual error message that mingw-w64 is giving you? |
From: K. F. <kfr...@gm...> - 2013-01-15 22:06:03
|
Hi Mike! On Tue, Jan 15, 2013 at 1:10 PM, Mike Gatny <mg...@co...> wrote: > It works with the VS compiler (32-bit, anyway). Can you post the actual > error message that mingw-w64 is giving you? Yes, I'd be happy to post the mingw-w64 error message. But before I do, I would like to check whether the code looks to you like it has an error, or whether I'm missing something simple about relatively basic c++. (Again the issue is that I see a pointer-to-pointer-to-function (double pointer) being passed, while a pointer-to-function (single pointer) is expected.) Does this look like an error to you? Anyway, here's the mingw-w64 error message: Utility.cpp: In function 'bool FIX::thread_spawn(unsigned int (*)(void*), void*, FIX::thread_id&)': Utility.cpp:510:56: error: cannot convert 'unsigned int (**)(void*)' to 'unsigned int (*)(void*)' for argument '3' to 'uintptr_t _beginthreadex(void*, unsigned int, unsigned int (*)(void*), void*, unsigned int, unsigned int*)' In a way, I'm not surprised that you don't see the issue with visual studio, because if you did, you would have changed the code. So I wonder whether visual studio might be doing something wrong or non-standard here. (I'm not aware of anything, but I'm not that expert with visual studio.) Or maybe g++ / mingw-w64 is doing something non-standard. But again, when I parse the code by eye, I come up with a type mismatch. (Just to note, the linux builds with g++ wouldn't have caught this because this is in the windows-specific part of the threading code. I verified -- at least to my eye -- that the analogous posix-threading part of the code doesn't have this issue.) By the way, if I "fix" the code by changing result = _beginthreadex( NULL, 0, &func, var, 0, &id ); to result = _beginthreadex( NULL, 0, func, var, 0, &id ); (that is, removing what appears to be the extra '&' from "&func") the code compiles under mingw-w64. I don't know whether the code runs correctly because I haven't been able to compile all of the rest of the code. But I would be worried about just making this change blindly because there is something going on that I don't understand. Thanks for helping me sort this out. K. Frank |
From: Djalma R. d. S. F. <drs...@gm...> - 2013-01-17 12:17:54
|
Hi Frank, Is the name of the function the function pointer itself? IMHO, this is just a matter of syntax and compiler implementation detail. You might want to check the C99 spec and the compiler documentation. Djalma On Tue, Jan 15, 2013 at 8:05 PM, K. Frank <kfr...@gm...> wrote: > QuickFIX Documentation: > http://www.quickfixengine.org/quickfix/doc/html/index.html > QuickFIX Support: http://www.quickfixengine.org/services.html > > Hi Mike! > > On Tue, Jan 15, 2013 at 1:10 PM, Mike Gatny <mg...@co...> wrote: > > It works with the VS compiler (32-bit, anyway). Can you post the actual > > error message that mingw-w64 is giving you? > > Yes, I'd be happy to post the mingw-w64 error message. > > But before I do, I would like to check whether the code looks to you > like it has an error, or whether I'm missing something simple about > relatively basic c++. (Again the issue is that I see a > pointer-to-pointer-to-function (double pointer) being passed, while a > pointer-to-function (single pointer) is expected.) Does this look > like an error to you? > > Anyway, here's the mingw-w64 error message: > > Utility.cpp: In function 'bool FIX::thread_spawn(unsigned int > (*)(void*), void*, FIX::thread_id&)': > Utility.cpp:510:56: error: cannot convert 'unsigned int > (**)(void*)' to 'unsigned int (*)(void*)' for argument '3' to > 'uintptr_t _beginthreadex(void*, unsigned int, unsigned int > (*)(void*), void*, unsigned int, unsigned int*)' > > In a way, I'm not surprised that you don't see the issue with visual > studio, because if you did, you would have changed the code. So > I wonder whether visual studio might be doing something wrong or > non-standard here. (I'm not aware of anything, but I'm not that > expert with visual studio.) Or maybe g++ / mingw-w64 is doing > something non-standard. But again, when I parse the code by > eye, I come up with a type mismatch. > > (Just to note, the linux builds with g++ wouldn't have caught this > because this is in the windows-specific part of the threading code. > I verified -- at least to my eye -- that the analogous posix-threading > part of the code doesn't have this issue.) > > By the way, if I "fix" the code by changing > > result = _beginthreadex( NULL, 0, &func, var, 0, &id ); > > to > > result = _beginthreadex( NULL, 0, func, var, 0, &id ); > > (that is, removing what appears to be the extra '&' from "&func") > the code compiles under mingw-w64. I don't know whether the > code runs correctly because I haven't been able to compile all > of the rest of the code. But I would be worried about just making > this change blindly because there is something going on that I > don't understand. > > > Thanks for helping me sort this out. > > > K. Frank > > > ------------------------------------------------------------------------------ > Master SQL Server Development, Administration, T-SQL, SSAS, SSIS, SSRS > and more. Get SQL Server skills now (including 2012) with LearnDevNow - > 200+ hours of step-by-step video tutorials by Microsoft MVPs and experts. > SALE $99.99 this month only - learn more at: > http://p.sf.net/sfu/learnmore_122512 > _______________________________________________ > Quickfix-developers mailing list > Qui...@li... > https://lists.sourceforge.net/lists/listinfo/quickfix-developers > |
From: K. F. <kfr...@gm...> - 2013-01-17 13:16:45
|
Hello Djalma! Thanks for taking a look at this. On Thu, Jan 17, 2013 at 7:17 AM, Djalma Rosa dos Santos Filho <drs...@gm...> wrote: > > Hi Frank, > > Is the name of the function the function pointer itself? As I understand c++ (and c), yes. When you use the name of a it "decays" into a function pointer (in the same way that the name of an array decays into a pointer to the first element of the array). > IMHO, this is just a matter of syntax and compiler implementation detail. > You might want to check the C99 spec and the compiler documentation. It is syntax, but I think it's standardized, and therefore it shouldn't be a compiler-specific detail. Also, the unix branch for the code (line 488 of Utility.cpp): if( pthread_create( &result, 0, func, var ) != 0 ) return false; does not have the '&' on "func" and compiles fine. Note, that "func" is not the name of a function, but rather a formal argument to the thread_spawn function (line 479): bool thread_spawn( THREAD_START_ROUTINE func, void* var, thread_id& thread ) (If I parse the typedef of THREAD_START_ROUTINE correctly, THREAD_START_ROUTINE is indeed a pointer to a function in both the windows and unix branches of the code.) So the unix branch looks right -- func is a function pointer, and there is no '&' to take the pointer to the pointer. But the windows branch (line 484): result = _beginthreadex( NULL, 0, &func, var, 0, &id ); has the '&' so "&func" is a pointer to func (the address of wherever func is stored on the stack when thread_spawn is called), and func is a pointer to a function, so "&func" is, as I read t, a pointer-to-pointer-to-function. What I don't understand, following up on Mike's comment, is why this would compile with visual studio. (I don't have visual studio to test.) To me it looks like a straightforward c++ issue. Either visual studio is doing something non-standard (wrong), of I've missed a different typedef hidden somewhere in an #ifdef somewhere in the windows branch of the code. (But, if so, it would be a typedef that mingw-w64 isn't picking up on.) So I think "&func" is an error. But I am also puzzled, because it compiles with visual studio, which doesn't make sense to me. > Djalma Thanks for your help. K. Frank > On Tue, Jan 15, 2013 at 8:05 PM, K. Frank <kfr...@gm...> wrote: >> >> Hi Mike! >> >> On Tue, Jan 15, 2013 at 1:10 PM, Mike Gatny <mg...@co...> wrote: >> > It works with the VS compiler (32-bit, anyway). Can you post the actual >> > error message that mingw-w64 is giving you? >> >> Yes, I'd be happy to post the mingw-w64 error message. >> >> But before I do, I would like to check whether the code looks to you >> like it has an error, or whether I'm missing something simple about >> relatively basic c++. (Again the issue is that I see a >> pointer-to-pointer-to-function (double pointer) being passed, while a >> pointer-to-function (single pointer) is expected.) Does this look >> like an error to you? >> >> Anyway, here's the mingw-w64 error message: >> >> Utility.cpp: In function 'bool FIX::thread_spawn(unsigned int >> (*)(void*), void*, FIX::thread_id&)': >> Utility.cpp:510:56: error: cannot convert 'unsigned int >> (**)(void*)' to 'unsigned int (*)(void*)' for argument '3' to >> 'uintptr_t _beginthreadex(void*, unsigned int, unsigned int >> (*)(void*), void*, unsigned int, unsigned int*)' >> >> In a way, I'm not surprised that you don't see the issue with visual >> studio, because if you did, you would have changed the code. So >> I wonder whether visual studio might be doing something wrong or >> non-standard here. (I'm not aware of anything, but I'm not that >> expert with visual studio.) Or maybe g++ / mingw-w64 is doing >> something non-standard. But again, when I parse the code by >> eye, I come up with a type mismatch. >> >> (Just to note, the linux builds with g++ wouldn't have caught this >> because this is in the windows-specific part of the threading code. >> I verified -- at least to my eye -- that the analogous posix-threading >> part of the code doesn't have this issue.) >> >> By the way, if I "fix" the code by changing >> >> result = _beginthreadex( NULL, 0, &func, var, 0, &id ); >> >> to >> >> result = _beginthreadex( NULL, 0, func, var, 0, &id ); >> >> (that is, removing what appears to be the extra '&' from "&func") >> the code compiles under mingw-w64. I don't know whether the >> code runs correctly because I haven't been able to compile all >> of the rest of the code. But I would be worried about just making >> this change blindly because there is something going on that I >> don't understand. >> >> Thanks for helping me sort this out. >> >> K. Frank >> ... |
From: Djalma R. d. S. F. <drs...@gm...> - 2013-01-17 13:53:41
|
In the last couple of years, Microsoft has made a huge effort to be compliant with the C/C++ standard. Perhaps, the problem relies in the fact that you are using MinGW which has been forced to conform to C89. http://www.mingw.org/wiki/C99 If so, you are right, an #ifdef for mingw would fix it. But, why don't you try Visual Studio Express for free? On Thu, Jan 17, 2013 at 11:16 AM, K. Frank <kfr...@gm...> wrote: > QuickFIX Documentation: > http://www.quickfixengine.org/quickfix/doc/html/index.html > QuickFIX Support: http://www.quickfixengine.org/services.html > > Hello Djalma! > > Thanks for taking a look at this. > > On Thu, Jan 17, 2013 at 7:17 AM, Djalma Rosa dos Santos Filho > <drs...@gm...> wrote: > > > > Hi Frank, > > > > Is the name of the function the function pointer itself? > > As I understand c++ (and c), yes. When you use the name of a > it "decays" into a function pointer (in the same way that the name > of an array decays into a pointer to the first element of the array). > > > IMHO, this is just a matter of syntax and compiler implementation detail. > > You might want to check the C99 spec and the compiler documentation. > > It is syntax, but I think it's standardized, and therefore it shouldn't > be a compiler-specific detail. > > Also, the unix branch for the code (line 488 of Utility.cpp): > > if( pthread_create( &result, 0, func, var ) != 0 ) return false; > > does not have the '&' on "func" and compiles fine. Note, that "func" > is not the name of a function, but rather a formal argument to the > thread_spawn function (line 479): > > bool thread_spawn( THREAD_START_ROUTINE func, void* var, thread_id& > thread ) > > (If I parse the typedef of THREAD_START_ROUTINE correctly, > THREAD_START_ROUTINE is indeed a pointer to a function in > both the windows and unix branches of the code.) > > So the unix branch looks right -- func is a function pointer, and > there is no '&' to take the pointer to the pointer. > > But the windows branch (line 484): > > result = _beginthreadex( NULL, 0, &func, var, 0, &id ); > > has the '&' so "&func" is a pointer to func (the address of wherever > func is stored on the stack when thread_spawn is called), and > func is a pointer to a function, so "&func" is, as I read t, a > pointer-to-pointer-to-function. > > What I don't understand, following up on Mike's comment, is > why this would compile with visual studio. (I don't have visual > studio to test.) To me it looks like a straightforward c++ issue. > Either visual studio is doing something non-standard (wrong), > of I've missed a different typedef hidden somewhere in an > #ifdef somewhere in the windows branch of the code. (But, if > so, it would be a typedef that mingw-w64 isn't picking up on.) > > So I think "&func" is an error. But I am also puzzled, because > it compiles with visual studio, which doesn't make sense to me. > > > Djalma > > > Thanks for your help. > > > K. Frank > > > > On Tue, Jan 15, 2013 at 8:05 PM, K. Frank <kfr...@gm...> wrote: > >> > >> Hi Mike! > >> > >> On Tue, Jan 15, 2013 at 1:10 PM, Mike Gatny <mg...@co...> > wrote: > >> > It works with the VS compiler (32-bit, anyway). Can you post the > actual > >> > error message that mingw-w64 is giving you? > >> > >> Yes, I'd be happy to post the mingw-w64 error message. > >> > >> But before I do, I would like to check whether the code looks to you > >> like it has an error, or whether I'm missing something simple about > >> relatively basic c++. (Again the issue is that I see a > >> pointer-to-pointer-to-function (double pointer) being passed, while a > >> pointer-to-function (single pointer) is expected.) Does this look > >> like an error to you? > >> > >> Anyway, here's the mingw-w64 error message: > >> > >> Utility.cpp: In function 'bool FIX::thread_spawn(unsigned int > >> (*)(void*), void*, FIX::thread_id&)': > >> Utility.cpp:510:56: error: cannot convert 'unsigned int > >> (**)(void*)' to 'unsigned int (*)(void*)' for argument '3' to > >> 'uintptr_t _beginthreadex(void*, unsigned int, unsigned int > >> (*)(void*), void*, unsigned int, unsigned int*)' > >> > >> In a way, I'm not surprised that you don't see the issue with visual > >> studio, because if you did, you would have changed the code. So > >> I wonder whether visual studio might be doing something wrong or > >> non-standard here. (I'm not aware of anything, but I'm not that > >> expert with visual studio.) Or maybe g++ / mingw-w64 is doing > >> something non-standard. But again, when I parse the code by > >> eye, I come up with a type mismatch. > >> > >> (Just to note, the linux builds with g++ wouldn't have caught this > >> because this is in the windows-specific part of the threading code. > >> I verified -- at least to my eye -- that the analogous posix-threading > >> part of the code doesn't have this issue.) > >> > >> By the way, if I "fix" the code by changing > >> > >> result = _beginthreadex( NULL, 0, &func, var, 0, &id ); > >> > >> to > >> > >> result = _beginthreadex( NULL, 0, func, var, 0, &id ); > >> > >> (that is, removing what appears to be the extra '&' from "&func") > >> the code compiles under mingw-w64. I don't know whether the > >> code runs correctly because I haven't been able to compile all > >> of the rest of the code. But I would be worried about just making > >> this change blindly because there is something going on that I > >> don't understand. > >> > >> Thanks for helping me sort this out. > >> > >> K. Frank > >> ... > > > ------------------------------------------------------------------------------ > Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS, > MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current > with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft > MVPs and experts. ON SALE this month only -- learn more at: > http://p.sf.net/sfu/learnmore_122712 > _______________________________________________ > Quickfix-developers mailing list > Qui...@li... > https://lists.sourceforge.net/lists/listinfo/quickfix-developers > |
From: K. F. <kfr...@gm...> - 2013-01-17 14:30:35
|
Hi Djalma! Thanks for the follow-up. On Thu, Jan 17, 2013 at 8:53 AM, Djalma Rosa dos Santos Filho <drs...@gm...> wrote: > > In the last couple of years, Microsoft has made a huge effort to be compliant with the C/C++ standard. > Perhaps, the problem relies in the fact that you are using MinGW which has been forced to conform to C89. I don't think this is the explanation. First off, this is all C++, not C or C89. Second mingw-w64 is very compliant. (Not perfect, but what is?) Third, there really shouldn't be any mystery here. The code looks pretty straightforward here, and according to my reading of the standard, the '&' in "&func" is an error. I could well be wrong, but I'd like to know specifically what I'm wrong about. > http://www.mingw.org/wiki/C99 Again, C99 is not directly relevant. C++ is. But I'm not aware of any relevant changes to function-pointer syntax that have occurred between the various versions of C and of C++. > If so, you are right, an #ifdef for mingw would fix it. Indeed. But maybe such an #ifdef isn't needed. Perhaps "func" (without the '&') would also work for visual studio. > But, why don't you try Visual Studio Express for free? Compatibility issues with other code that isn't specifically part of QuickFIX. I appreciate your help with this. K. Frank > ... > On Thu, Jan 17, 2013 at 11:16 AM, K. Frank <kfr...@gm...> wrote: >> >> Hello Djalma! >> >> Thanks for taking a look at this. >> >> On Thu, Jan 17, 2013 at 7:17 AM, Djalma Rosa dos Santos Filho >> <drs...@gm...> wrote: >> > >> > Hi Frank, >> > >> > Is the name of the function the function pointer itself? >> >> As I understand c++ (and c), yes. When you use the name of a >> it "decays" into a function pointer (in the same way that the name >> of an array decays into a pointer to the first element of the array). >> >> > IMHO, this is just a matter of syntax and compiler implementation detail. >> > You might want to check the C99 spec and the compiler documentation. >> >> It is syntax, but I think it's standardized, and therefore it shouldn't >> be a compiler-specific detail. >> >> Also, the unix branch for the code (line 488 of Utility.cpp): >> >> if( pthread_create( &result, 0, func, var ) != 0 ) return false; >> >> does not have the '&' on "func" and compiles fine. Note, that "func" >> is not the name of a function, but rather a formal argument to the >> thread_spawn function (line 479): >> >> bool thread_spawn( THREAD_START_ROUTINE func, void* var, thread_id& thread ) >> >> (If I parse the typedef of THREAD_START_ROUTINE correctly, >> THREAD_START_ROUTINE is indeed a pointer to a function in >> both the windows and unix branches of the code.) >> >> So the unix branch looks right -- func is a function pointer, and >> there is no '&' to take the pointer to the pointer. >> >> But the windows branch (line 484): >> >> result = _beginthreadex( NULL, 0, &func, var, 0, &id ); >> >> has the '&' so "&func" is a pointer to func (the address of wherever >> func is stored on the stack when thread_spawn is called), and >> func is a pointer to a function, so "&func" is, as I read t, a >> pointer-to-pointer-to-function. >> >> What I don't understand, following up on Mike's comment, is >> why this would compile with visual studio. (I don't have visual >> studio to test.) To me it looks like a straightforward c++ issue. >> Either visual studio is doing something non-standard (wrong), >> of I've missed a different typedef hidden somewhere in an >> #ifdef somewhere in the windows branch of the code. (But, if >> so, it would be a typedef that mingw-w64 isn't picking up on.) >> >> So I think "&func" is an error. But I am also puzzled, because >> it compiles with visual studio, which doesn't make sense to me. >> >> > Djalma >> >> Thanks for your help. >> >> K. Frank >> ... |
From: Djalma R. d. S. F. <drs...@gm...> - 2013-01-22 17:34:58
|
Hi Frank, Sorry, I thought that it had something to do with the C spec because _beginthreadex belongs to the C runtime libraries and mingw is a gcc port that relies in the obsolete VC 6 (according to the project's wiki). Actually, I was curious and then I found out that the ampersand (&) to specify the address of a function is optional for Visual C++ compiler. It means that utility.cpp will compile under msvc with or without the & in front of func. Indeed, it is very weird but for non-static member functions it would be required. error C3867: 'MyStruct::f': function call missing argument list; use '&MyStruct::f' to create a pointer to member Maybe we can conclude that it is a bug in mingw for not accepting the optional ampersand (C language) and an inconsistency in the C++ language for having different rules for static and non-static member functions. What is your opinion? Check these links for more clarification: http://www.velocityreviews.com/forums/t277815-pointer-to-member-functions-is-and-required.html http://msdn.microsoft.com/en-us/library/ms177253%28v=vs.80%29.aspx Djalma On Thu, Jan 17, 2013 at 12:30 PM, K. Frank <kfr...@gm...> wrote: > QuickFIX Documentation: > http://www.quickfixengine.org/quickfix/doc/html/index.html > QuickFIX Support: http://www.quickfixengine.org/services.html > > Hi Djalma! > > Thanks for the follow-up. > > On Thu, Jan 17, 2013 at 8:53 AM, Djalma Rosa dos Santos Filho > <drs...@gm...> wrote: > > > > In the last couple of years, Microsoft has made a huge effort to be > compliant with the C/C++ standard. > > Perhaps, the problem relies in the fact that you are using MinGW which > has been forced to conform to C89. > > I don't think this is the explanation. > > First off, this is all C++, not C or C89. Second mingw-w64 is very > compliant. (Not perfect, but what is?) Third, there really shouldn't > be any mystery here. The code looks pretty straightforward here, > and according to my reading of the standard, the '&' in "&func" is > an error. I could well be wrong, but I'd like to know specifically what > I'm wrong about. > > > http://www.mingw.org/wiki/C99 > > Again, C99 is not directly relevant. C++ is. But I'm not aware of any > relevant changes to function-pointer syntax that have occurred between > the various versions of C and of C++. > > > If so, you are right, an #ifdef for mingw would fix it. > > Indeed. But maybe such an #ifdef isn't needed. Perhaps "func" (without > the '&') would also work for visual studio. > > > But, why don't you try Visual Studio Express for free? > > Compatibility issues with other code that isn't specifically part of > QuickFIX. > > > I appreciate your help with this. > > > K. Frank > > > > ... > > On Thu, Jan 17, 2013 at 11:16 AM, K. Frank <kfr...@gm...> wrote: > >> > >> Hello Djalma! > >> > >> Thanks for taking a look at this. > >> > >> On Thu, Jan 17, 2013 at 7:17 AM, Djalma Rosa dos Santos Filho > >> <drs...@gm...> wrote: > >> > > >> > Hi Frank, > >> > > >> > Is the name of the function the function pointer itself? > >> > >> As I understand c++ (and c), yes. When you use the name of a > >> it "decays" into a function pointer (in the same way that the name > >> of an array decays into a pointer to the first element of the array). > >> > >> > IMHO, this is just a matter of syntax and compiler implementation > detail. > >> > You might want to check the C99 spec and the compiler documentation. > >> > >> It is syntax, but I think it's standardized, and therefore it shouldn't > >> be a compiler-specific detail. > >> > >> Also, the unix branch for the code (line 488 of Utility.cpp): > >> > >> if( pthread_create( &result, 0, func, var ) != 0 ) return false; > >> > >> does not have the '&' on "func" and compiles fine. Note, that "func" > >> is not the name of a function, but rather a formal argument to the > >> thread_spawn function (line 479): > >> > >> bool thread_spawn( THREAD_START_ROUTINE func, void* var, thread_id& > thread ) > >> > >> (If I parse the typedef of THREAD_START_ROUTINE correctly, > >> THREAD_START_ROUTINE is indeed a pointer to a function in > >> both the windows and unix branches of the code.) > >> > >> So the unix branch looks right -- func is a function pointer, and > >> there is no '&' to take the pointer to the pointer. > >> > >> But the windows branch (line 484): > >> > >> result = _beginthreadex( NULL, 0, &func, var, 0, &id ); > >> > >> has the '&' so "&func" is a pointer to func (the address of wherever > >> func is stored on the stack when thread_spawn is called), and > >> func is a pointer to a function, so "&func" is, as I read t, a > >> pointer-to-pointer-to-function. > >> > >> What I don't understand, following up on Mike's comment, is > >> why this would compile with visual studio. (I don't have visual > >> studio to test.) To me it looks like a straightforward c++ issue. > >> Either visual studio is doing something non-standard (wrong), > >> of I've missed a different typedef hidden somewhere in an > >> #ifdef somewhere in the windows branch of the code. (But, if > >> so, it would be a typedef that mingw-w64 isn't picking up on.) > >> > >> So I think "&func" is an error. But I am also puzzled, because > >> it compiles with visual studio, which doesn't make sense to me. > >> > >> > Djalma > >> > >> Thanks for your help. > >> > >> K. Frank > >> ... > > > ------------------------------------------------------------------------------ > Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS, > MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current > with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft > MVPs and experts. ON SALE this month only -- learn more at: > http://p.sf.net/sfu/learnmore_122712 > _______________________________________________ > Quickfix-developers mailing list > Qui...@li... > https://lists.sourceforge.net/lists/listinfo/quickfix-developers > |
From: K. F. <kfr...@gm...> - 2013-01-22 18:38:44
|
Hi Djalma - On Tue, Jan 22, 2013 at 12:34 PM, Djalma Rosa dos Santos Filho <drs...@gm...> wrote: > > Hi Frank, > > Sorry, I thought that it had something to do with the C spec because _beginthreadex belongs to the C runtime libraries and mingw is a gcc port that relies in the obsolete VC 6 (according to the project's wiki). First, I'm using mingw-w64 which is a different project than mingw. Second, I wouldn't be surprised is the mingw wiki is out of date. Third, my guess is that mingw was never trying to be consistent with language idiosyncrasies of VC6. It is a port of gcc, so I think they were -- both by default and by intent -- sticking with the gcc "interpretation" of the language. Mingw does want to interoperate with VC (although not necessarily anything as old as 6) in the sense of ABI compatibility (with C, and where possible). > Actually, I was curious and then I found out that the ampersand (&) to specify the address of a function is optional for Visual C++ compiler. It means that utility.cpp will compile under msvc with or without the & in front of func. I believe that '&' is optional for taking the address of a function in the standard (not just VC). That is void f() {} void (*fp) (); fp = f; // these two line are equivalent fp = &f; // these two line are equivalent But that is not what we're doing. "func" in the thread_spawn call is a formal argument (that happens to be a pointer to a function), and is stored on the stack when thread_spawn is called. "func" is not a function, in the technical sense that "f" is a function in the example above. So &func is the address on the stack where the value of the argument func is stored. &func and func are not the same, and (if you want a pointer to a pointer) there is nothing optional about the '&'. > > Indeed, it is very weird but for non-static member functions it would be required. Well, pointers to member functions are different, both in what they actually are, and in syntax. > error C3867: 'MyStruct::f': function call missing argument list; use '&MyStruct::f' to create a pointer to member > > Maybe we can conclude that it is a bug in mingw for not accepting the optional ampersand (C language) and an inconsistency in the C++ language for having different rules for static and non-static member functions. I think mingw-w64 is correct. Also, as explained above, the case we're dealing with is not the case where the '&' is optional. > What is your opinion? I can't figure out how the code could work. When func is a pointer to a function, then &func is a pointer to (the address of) that pointer. I can't imagine that VC doesn't do it that way, because if VC didn't, it would break a lot of code. And if VC is taking the pointer to the pointer, then 1) the code in question shouldn't compile, and 2) the code should fail. > Check these links for more clarification: > http://www.velocityreviews.com/forums/t277815-pointer-to-member-functions-is-and-required.html > http://msdn.microsoft.com/en-us/library/ms177253%28v=vs.80%29.aspx The question of pointers to member functions is an interesting side issue, but is not directly relevant to the case of free functions, which is what we're discussing. > Djalma Thanks for looking into this. K. Frank > On Thu, Jan 17, 2013 at 12:30 PM, K. Frank <kfr...@gm...> wrote: >> >> Hi Djalma! >> >> Thanks for the follow-up. >> >> On Thu, Jan 17, 2013 at 8:53 AM, Djalma Rosa dos Santos Filho >> <drs...@gm...> wrote: >> > >> > In the last couple of years, Microsoft has made a huge effort to be compliant with the C/C++ standard. >> > Perhaps, the problem relies in the fact that you are using MinGW which has been forced to conform to C89. >> >> I don't think this is the explanation. >> >> First off, this is all C++, not C or C89. Second mingw-w64 is very >> compliant. (Not perfect, but what is?) Third, there really shouldn't >> be any mystery here. The code looks pretty straightforward here, >> and according to my reading of the standard, the '&' in "&func" is >> an error. I could well be wrong, but I'd like to know specifically what >> I'm wrong about. >> >> > http://www.mingw.org/wiki/C99 >> >> Again, C99 is not directly relevant. C++ is. But I'm not aware of any >> relevant changes to function-pointer syntax that have occurred between >> the various versions of C and of C++. >> >> > If so, you are right, an #ifdef for mingw would fix it. >> >> Indeed. But maybe such an #ifdef isn't needed. Perhaps "func" (without >> the '&') would also work for visual studio. >> >> > But, why don't you try Visual Studio Express for free? >> >> Compatibility issues with other code that isn't specifically part of >> QuickFIX. >> >> I appreciate your help with this. >> >> K. Frank >> ... |
From: Djalma R. d. S. F. <drs...@gm...> - 2013-01-22 19:52:37
|
On Tue, Jan 22, 2013 at 4:38 PM, K. Frank <kfr...@gm...> wrote: > "func" in the thread_spawn call is a formal argument (that > happens to be a pointer to a function), and is stored on > the stack when thread_spawn is called. "func" is not a > function, in the technical sense that "f" is a function in the > example above. So &func is the address on the stack where > the value of the argument func is stored. &func and func > are not the same, and (if you want a pointer to a pointer) > there is nothing optional about the '&'. > Well, I think you are correct here. Indeed, if you get the function pointer declaration in utility.h it is missing the expected * just after _stdcall, but the compiler does not care. #ifdef _MSC_VER typedef unsigned int (_stdcall THREAD_START_ROUTINE)(void *); After fixing the declaration, typedef unsigned int (_stdcall *THREAD_START_ROUTINE)(void *); and trying to use &func the compiler starts to complain as expected, although with a weired error message. 1>.\Utility.cpp(517) : error C2664: '_beginthreadex' : cannot convert parameter 3 from 'FIX::THREAD_START_ROUTINE *' to 'unsigned int (__cdecl *)(void *)' I believe that for some kind of magic behind the scenes (that I definitively would not dare to try to explain), everything works fine and the compiler currently generates the correct code for Windows platform. It is really very confusing issue. Unfortunately I don't have VC11/VC12 at the momento to check whether this is something that was fixed in newer versions of Microsoft compiler. |