From: <mar...@ma...> - 2007-02-23 13:31:33
|
Hello mingw-users, please forgive my ignorance, but after a day of fruitless search I'm = more or less forced to put this question in here: I tried to build GNU Global in the current = release 5.4 on a newly installed MinGW but in the make run (right after ./configure) when = linking the executable I get the error that the reference to 'setenv' couldn't be resolved. A = check of all header files reveals that setenv is really not there, just 'getenv' can be found in = stdlib.h. I resolved the problem for the moment by commenting the call to setenv out, but I = suppose there must be a way to supply MinGW with a setenv-like functionality as there are = surely several apps out there which really rely on it (more than Global). regards, Mark PS: it is really my first time delving into Unix-oriented programming, = so please bear a little with my ignorance on certain concepts=20 This message is not legally binding upon our company! This communication is confidential and is intended solely for the addressee(s). If you are not the intended recipient(s), his/her assistant, or authorized recipient, any form of disclosure, reproduction, distribution or any use of this communication or the information in it, is strictly prohibited and may be unlawful. In this case, please notify the sender immediately and destroy the e-mail. Electronic communication via the Internet by e-mail may be manipulated and/or read by third parties, thus we exclude any liability whatsoever for this e-mail. |
From: Keith M. <kei...@to...> - 2007-02-23 15:21:42
|
Mark Piffer wrote: > I get the error that the reference to 'setenv' couldn't be > resolved. That's correct. MinGW uses the MSVCRT runtime library, which provides no such function. > A check of all header files reveals that setenv is really not > there, just 'getenv' can be found in stdlib.h. The important criterion isn't what's defined in the headers, but rather what is provided by the runtime library. > I resolved the problem for the moment by commenting the call > to setenv out, Which means your application now isn't behaving as it should, for it is no longer able to modify it's environment. > but I suppose there must be a way to supply MinGW with a > setenv-like functionality It already has it -- it uses the putenv function. > as there are surely several apps out there which really rely > on it (more than Global). IMO, Global is broken. There are two common standard functions for manipulating the environment, viz. setenv and putenv. Some systems provide both, some only setenv, and others, like Woe32, only provide putenv. Any portable application needs to check, via its configure script, to determine which of these APIs is supported, and then deploy the correct one in its code. FWIW, here's a sample from the code for man: static void mysetenv(const char *name, const char *value) { #ifdef HAVE_SETENV setenv(name, value, 1); #else int len = strlen(value)+1+strlen(value)+1; char *str = my_malloc(len); sprintf(str, "%s=%s", name, value); putenv(str); #endif } This relies on the the configure script checking for the availability of the setenv function, and adding an appropriate definition to config.h, when it is present; it unconditionally assumes that putenv will be available, if setenv isn't, which is perhaps an unsafe assumption, but if neither is available the code will simply fail to link anyway. Do also note that the APIs for the two functions are not the same; with putenv we say: putenv( "NAME=VALUE" ); whereas with setenv we have to say: setenv( "NAME", "VALUE", OVERWRITE_OPTION ); HTH, Keith. |
From: Daniel K. O. <dan...@gm...> - 2007-02-23 15:52:33
|
Keith MARSHALL escreveu: > Do also note that the APIs for the two functions are not the > same; with putenv we say: > > putenv( "NAME=VALUE" ); > > whereas with setenv we have to say: > > setenv( "NAME", "VALUE", OVERWRITE_OPTION ); Just to complement the answer: watch out for the different semantics between putenv and setenv. Even though the mysetenv() code seems to leak memory, that's necessary for putenv() - it doesn't copy the argument, it just points to it; so if you change (or free) the string after the putenv() call, you may mess with the environment. So make sure the argument is either a string literal, or dynamically allocated. --- Daniel K. O. |
From: Keith M. <kei...@to...> - 2007-02-23 16:38:16
|
Daniel K. O. wrote: > Even though the mysetenv() code seems to > leak memory, that's necessary for putenv() - it doesn't copy the > argument, it just points to it; so if you change (or free) the > string after the putenv() call, you may mess with the environment. `seems' is very much the operative word here, for the mysetenv example does *not* leak memory, *if* the putenv call is successful. Yes, the pointer to the string eventually passed to putenv is not directly exposed beyond the scope of mysetenv; it is a local pointer to a malloc'ed buffer, so the buffer continues to exist after mysetenv returns, but the pointer is lost; however, it may be retrieved subsequently, by calling getenv. BTW, I didn't write that sample function; it is exactly as it was in the man-1.5m sources I ported, and may very well be John Eaton's original code. I guess it could be made more robust by free'ing the buffer before returning, if the putenv call fails: static void mysetenv(const char *name, const char *value) { #ifdef HAVE_SETENV setenv(name, value, 1); #else int len = strlen(value)+1+strlen(value)+1; char *str = my_malloc(len); sprintf(str, "%s=%s", name, value); if(putenv(str) != EXIT_SUCCESS) free(str); #endif } (The my_malloc function is a wrapper around malloc; it aborts the program, with an `Out of memory' message, if malloc itself fails). Regards, Keith. |
From: David D. <dav...@rs...> - 2007-02-23 16:44:59
|
On Fri, 2007-02-23 at 16:31 +0000, Keith MARSHALL wrote: > int len = strlen(value)+1+strlen(value)+1; Shouldn't that read: int len = strlen(name)+1+strlen(value)+1; ^^^^ Otherwise you could have a buffer overrun with the sprintf call. |
From: Keith M. <kei...@to...> - 2007-02-23 17:06:17
|
David Daeschler wrote: >> int len = strlen(value)+1+strlen(value)+1; > > Shouldn't that read: > int len = strlen(name)+1+strlen(value)+1; > ^^^^ > > Otherwise you could have a buffer overrun with the sprintf call. You are absolutely right. And that bug has been present in the official man sources, probably since the beginning. I'll fix it, in my port to MinGW, and send a bug report to the maintainer of the official package. Well spotted. Thanks for the report. Regards, Keith. |
From: Tor L. <tm...@ik...> - 2007-02-23 17:16:08
|
Daniel K. O. writes: > that's necessary for putenv() - it doesn't copy the argument, it > just points to it It does? Try compiling the following program against msvcrt.dll: #include <string.h> #include <stdio.h> #include <stdlib.h> int main (int argc, char **argv) { char assignment[100]; strcpy (assignment, "FOO=bar"); putenv (assignment); strcpy (assignment, "WTF=eh?"); printf ("getenv (\"FOO\") = \"%s\"\n", getenv ("FOO") ? getenv ("FOO") : "<null>"); printf ("getenv (\"WTF\") = \"%s\"\n", getenv ("WTF") ? getenv ("WTF") : "<null>"); return 0; } If what you say is true, the getenv("WTF") call should return "eh?", shouldn't it? Looking at the sources for Microsoft'c putenv() also verifies that putenv() indeed *does* copy its argument to dynamically allocated memory. --tml |
From: Daniel K. O. <dan...@gm...> - 2007-02-23 19:11:17
|
Tor Lillqvist escreveu: > Daniel K. O. writes: > > that's necessary for putenv() - it doesn't copy the argument, it > > just points to it > > It does? > Well, I was just pointing the remark on the GNU libc documentation, that claims "This function is part of the extended Unix interface", so I assume it's the most widely expected behavior. Of course, you can easily implement one that works differently from the rest of the world - and looks Microsoft likes this approach. Good thing environment variables are mostly useless on Win32. > Looking at the sources for Microsoft'c putenv() also verifies that > putenv() indeed *does* copy its argument to dynamically allocated > memory. > Thanks for the information. Now, looking at autoconf documentation, there's a bit on this: `putenv' POSIX specifies that `putenv' puts the given string directly in `environ', but some systems make a copy of it instead (eg. glibc 2.0, or BSD). And when a copy is made, `unsetenv' might not free it, causing a memory leak (eg. FreeBSD 4). POSIX specifies that `putenv("FOO")' removes `FOO' from the environment, but on some systems (eg. FreeBSD 4) this is not the case and instead `unsetenv' must be used. On MINGW, a call `putenv("FOO=")' removes `FOO' from the environment, rather than inserting it with an empty value. No mention about the copying vs. just pointing on MinGW. Now this seems a really tricky function. In practice, it shouldn't do any harm to leak a few small strings just once across all the program execution. But it's really troubling that there's no way to guarantee the semantics even across different unix implementations. -- Daniel K. O. |
From: James S. <jam...@op...> - 2007-02-23 20:04:26
|
Hi Mark, On Fri, 2007-02-23 at 14:30 +0100, mar...@ma... wrote: > This message is not legally binding upon our company! This > communication is confidential and is intended solely for the > addressee(s). If you are not the intended recipient(s), his/her > assistant, or authorized recipient, any form of disclosure, > reproduction, distribution or any use of this communication or the > information in it, is strictly prohibited and may be unlawful. In this > case, please notify the sender immediately and destroy the e-mail. > Electronic communication via the Internet by e-mail may be manipulated > and/or read by third parties, thus we exclude any liability whatsoever > for this e-mail. Unfortunately your message is now available to all on the internet. So the bit above about confidentiality is, well ... disturbing. On other mailing lists such statements would get you banned. Regards, James. |
From: Keith M. <kei...@us...> - 2007-02-24 14:09:25
|
On Friday 23 February 2007 20:04, James Steward wrote: > On Fri, 2007-02-23 at 14:30 +0100, mar...@ma... wrote: > > This message is not legally binding upon our company! This > > communication is confidential and is intended solely for the > > addressee(s). If you are not the intended recipient(s), his/her > > assistant, or authorized recipient, any form of disclosure, > > reproduction, distribution or any use of this communication or the > > information in it, is strictly prohibited and may be unlawful. In > > this case, please notify the sender immediately and destroy the > > e-mail. Electronic communication via the Internet by e-mail may be > > manipulated and/or read by third parties, thus we exclude any > > liability whatsoever for this e-mail. > > Unfortunately your message is now available to all on the internet. > So the bit above about confidentiality is, well ... disturbing. In fact, since he's posted his message to a public mailing list, it is utterly meaningless, and quite unenforceable. > On other mailing lists such statements would get you banned. Unfortunately, some corporations insist on adding this sort of nonsense automatically, to every message sent through their mail servers, regardless of destination. While it is utterly ludicrous to attach this sort of verbiage to any message sent to a public mailing list, and I would encourage all subscribers to suppress such addenda, if it is in their power to do so, I will not take the draconian action of banning those who find it impossible to avoid this sort of corporate stupidity. Regards, Keith. |
From: James S. <jam...@op...> - 2007-02-24 20:20:39
|
On Sat, 2007-02-24 at 14:19 +0000, Keith Marshall wrote: > On Friday 23 February 2007 20:04, James Steward wrote: > > On Fri, 2007-02-23 at 14:30 +0100, mar...@ma... wrote: > > > This message is not legally binding upon our company! This > > > communication is confidential and is intended solely for the > > > addressee(s). If you are not the intended recipient(s), his/her > > > assistant, or authorized recipient, any form of disclosure, > > > reproduction, distribution or any use of this communication or the > > > information in it, is strictly prohibited and may be unlawful. In > > > this case, please notify the sender immediately and destroy the > > > e-mail. Electronic communication via the Internet by e-mail may be > > > manipulated and/or read by third parties, thus we exclude any > > > liability whatsoever for this e-mail. > > > > Unfortunately your message is now available to all on the internet. > > So the bit above about confidentiality is, well ... disturbing. > > In fact, since he's posted his message to a public mailing list, it is > utterly meaningless, and quite unenforceable. > > > On other mailing lists such statements would get you banned. > > Unfortunately, some corporations insist on adding this sort of nonsense > automatically, to every message sent through their mail servers, > regardless of destination. While it is utterly ludicrous to attach > this sort of verbiage to any message sent to a public mailing list, and > I would encourage all subscribers to suppress such addenda, if it is in > their power to do so, I will not take the draconian action of banning > those who find it impossible to avoid this sort of corporate stupidity. You are most kind. On a particular linux related list I've seen it suggested that folk with these sorts of unavoidable corporate added nonsense addenda use a gmail account or similar to circumvent their corporate mail servers interference. I don't mean to cause anyone stress btw. I thought this might be a useful suggestion. Regards, James. |
From: Greg C. <chi...@co...> - 2007-02-25 01:44:50
|
On 2007-2-24 20:20 UTC, James Steward wrote: > On Sat, 2007-02-24 at 14:19 +0000, Keith Marshall wrote: [silly automatically-appended corporate disclaimers] >> [...] I will not take the draconian action of banning >> those who find it impossible to avoid this sort of corporate stupidity. > > You are most kind. On a particular linux related list I've seen it > suggested that folk with these sorts of unavoidable corporate added > nonsense addenda use a gmail account or similar to circumvent their > corporate mail servers interference. In my office, a disclaimer is added to every email...and access to gmail and similar sites is blocked, though I'm not sure why. Maybe they suppose that people would use gmail for personal correspondence on company time. Or perhaps they fear that gmail would be used for company business, and wouldn't include the disclaimer. Probably some other large corporations act similarly, so gmail isn't always an option. |
From: Brian B. <br...@da...> - 2007-03-16 23:51:25
|
Hi, I'm trying to debug something. When I run the program normally, it 'dies' (no error message anywhere and my trace statements just suddenly stop). So I pulled out good ol' gdb, but the program 'works' there (ie, it doesn't die). The only reason I can think of is that gdb makes uninitialised memory more palatable to the bug in my program. So I want to know is 'baadf00d' a gdb magic number or is it a microsoft (specifically, DirectX DirectInput) thing? Thanks, Brian. |
From: Greg C. <chi...@co...> - 2007-03-17 00:22:17
|
On 2007-3-16 23:51 UTC, Brian Bruinewoud wrote: > > I'm trying to debug something. When I run the program normally, it > 'dies' (no error message anywhere and my trace statements just suddenly > stop). So I pulled out good ol' gdb, but the program 'works' there (ie, > it doesn't die). That's a common enough set of symptoms, > The only reason I can think of is that gdb makes > uninitialised memory more palatable to the bug in my program. and that could explain the different behavior, > So I want > to know is 'baadf00d' a gdb magic number or is it a microsoft > (specifically, DirectX DirectInput) thing? and a debugger might initialize all memory to a value like that so that you can see when a memory-block header gets stomped on. I thought gdb used 'deadbeef'; maybe google knows for sure. You could try a JIT debugger like 'drmingw'. It's easy to try, and there's a chance that it'll lead you right to the problem. If this is C++ and you suspect a problem with the way the standard library is used, you could rebuild from scratch with the warning macros defined. You could use a malloc debugger. That's harder than the other ideas above. It's apparently easier to do on a GNU/Linux system, if this is a cross-platform app. Aside from that, you can step through everything with a debugger (where the problem will be difficult to observe), or add print statements to localize the problem (running it outside the debugger). Sometimes the cause can be found by enabling strong warnings, if you haven't already. Sometimes it can be prevented by taking extra care--using snprintf() instead of printf(), asserting that pointers aren't null, etc. |
From: Brian B. <br...@da...> - 2007-03-17 00:53:56
|
Greg Chicares wrote: >On 2007-3-16 23:51 UTC, Brian Bruinewoud wrote: > > >>I'm trying to debug something. When I run the program normally, it >>'dies' (no error message anywhere and my trace statements just suddenly >>stop). So I pulled out good ol' gdb, but the program 'works' there (ie, >>it doesn't die). >> >> > >That's a common enough set of symptoms, > > >>So I want >>to know is 'baadf00d' a gdb magic number or is it a microsoft >>(specifically, DirectX DirectInput) thing? >> >> Seems to be an MS thing. Also worked out why I was seeing that particular value and fixed it. The program still aborts at the same place (according to my tracing via lots of print statements) and now works perfectly in the debugger (does what I want when I want). >You could try a JIT debugger like 'drmingw'. It's easy to >try, and there's a chance that it'll lead you right to the >problem. > > drmingw doesn't do anything. It works for the test programs, but not for mine. When I said that my code dies without error messages anywhere, that includes not showing the "<program> has encountered a problem and needs to close." dialog box from windows with the 'Debug' but. If you didn't know what to expect the program to do you'd think that it worked, however, looking at my trace log file, I can see that it hasn't even run the destructors that it should. >If this is C++ and you suspect a problem with the way the >standard library is used, you could rebuild from scratch >with the warning macros defined. > > What 'warning macros' are you referring to? >Aside from that, you can step through everything with a >debugger (where the problem will be difficult to observe), >or add print statements to localize the problem (running >it outside the debugger). > > Print statements always finish at a particular function, but the last batch of output may not have been properly flushed to the disk... >Sometimes the cause can be found by enabling strong >warnings, if you haven't already. Sometimes it can be >prevented by taking extra care--using snprintf() instead >of printf(), asserting that pointers aren't null, etc. > > I'm using -Wall and -Wextra and the only errors I get are unused function parameters. Should any other warnings be enabled? |
From: Daniel K. O. <dan...@gm...> - 2007-03-17 01:13:15
|
Brian Bruinewoud escreveu: > drmingw doesn't do anything. It works for the test programs, but not for > mine. When I said that my code dies without error messages anywhere, > that includes not showing the "<program> has encountered a problem and > needs to close." dialog box from windows with the 'Debug' but. > This happened to me a lot when overflowing the stack on Windows XP; the program would silently terminate (interestingly, Win98 boxes seem to always nicely crash, running the exactly same binary). So watch out for Windows' small stack sizes (if you need bigger stacks, you'll have to work around it explicitly). --- Daniel K. O. |
From: Greg C. <chi...@co...> - 2007-03-17 11:42:18
|
On 2007-3-17 0:53 UTC, Brian Bruinewoud wrote: > Greg Chicares wrote: [...] > The program still aborts at the same place (according to my tracing via > lots of print statements) and now works perfectly in the debugger (does > what I want when I want). A wild guess: maybe it's writing through a pointer that isn't initialized to point to memory the program owns, but with gdb it gets initialized to point somewhere that just happens not to be owned by any other program? >> You could try a JIT debugger like 'drmingw'. It's easy to >> try, and there's a chance that it'll lead you right to the >> problem. >> > drmingw doesn't do anything. It works for the test programs, but not for > mine. When I said that my code dies without error messages anywhere, > that includes not showing the "<program> has encountered a problem and > needs to close." dialog box from windows with the 'Debug' but. It has rarely told me anything useful. But when it does, it's magical. And it costs so little to use. > If you didn't know what to expect the program to do you'd think that it > worked, however, looking at my trace log file, I can see that it hasn't > even run the destructors that it should. I kept a log of problems I had that were like this. I found they mostly arose from using 'new' and 'delete', so I stopped managing memory in the application layer, and pushed it into a library layer (e.g., smart pointers) that's guarded with copious unit tests. And wherever possible I used the stack instead of the heap (I had lots of code from the 16-bit era that used the heap promiscuously, to avoid the 64K limit), and the C++ standard library instead of C-style code (e.g., std::string instead of new char[whatever]). I never had a large number of memory problems, but FWIW with these techniques I have far fewer now. >> If this is C++ and you suspect a problem with the way the >> standard library is used, you could rebuild from scratch >> with the warning macros defined. >> > What 'warning macros' are you referring to? -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCPP_DEBUG -D_GLIBCPP_DEBUG_PEDANTIC -D_GLIBCPP_CONCEPT_CHECKS -D_GLIBXX_DEBUG_PEDANTIC They've varied between versions, but it seems harmless to specify all variants. >> Aside from that, you can step through everything with a >> debugger (where the problem will be difficult to observe), >> or add print statements to localize the problem (running >> it outside the debugger). >> > Print statements always finish at a particular function, but the last > batch of output may not have been properly flushed to the disk... Good point. There's some msw function that's supposed to flush all buffers to disk...let's see...okay, it's _flushall(), but you have to link 'Commode.obj', which I guess requires ms tools: http://support.microsoft.com/kb/q148505/ | In 32-bit versions of Windows, the operating system has | built-in disk caching. The only way to force a file to be | flushed to disk is by linking to Commode.obj. but maybe that's not really the only way--this article: http://support.microsoft.com/kb/66052 mentions FlushFileBuffers() and _commit(), which might be worth a try. >> Sometimes the cause can be found by enabling strong >> warnings, if you haven't already. Sometimes it can be >> prevented by taking extra care--using snprintf() instead >> of printf(), asserting that pointers aren't null, etc. >> > I'm using -Wall and -Wextra and the only errors I get are unused > function parameters. Should any other warnings be enabled? Here's the complete set I use. ifeq (3.4.4,$(gcc_version)) # Suppress spurious gcc-3.4.4 warnings: # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22207 gcc_version_specific_warnings := -Wno-uninitialized endif treat_warnings_as_errors := -pedantic-errors -Werror gcc_common_warnings := \ $(treat_warnings_as_errors) \ -Wall \ -Wcast-align \ -Wconversion \ -Wdeprecated-declarations \ -Wdisabled-optimization \ -Wimport \ -Wmultichar \ -Wpacked \ -Wpointer-arith \ -Wsign-compare \ -Wundef \ -Wwrite-strings \ # Some libraries aren't compatible with these "extra" warnings. # (Use '-W' for backward compatibility, instead of the # modern equivalent '-Wextra'.) gcc_common_extra_warnings := \ -W \ -Wcast-qual \ -Wredundant-decls \ gcc_c_warnings := \ $(gcc_common_warnings) \ -std=c99 \ -Wmissing-prototypes \ gcc_cxx_warnings := \ $(gcc_common_warnings) \ -std=c++98 \ -Wctor-dtor-privacy \ -Wdeprecated \ -Wnon-template-friend \ -Woverloaded-virtual \ -Wpmf-conversions \ -Wsynth \ # Too many warnings for various boost libraries: # -Wold-style-cast \ # -Wshadow \ # Too many warnings for libstdc++: # -Wunreachable-code \ # For C: C_WARNINGS = \ $(gcc_c_warnings) \ $(gcc_common_extra_warnings) \ $(gcc_version_specific_warnings) \ # For C++: CXX_WARNINGS = \ $(gcc_cxx_warnings) \ $(gcc_common_extra_warnings) \ $(gcc_version_specific_warnings) \ |
From: Jonathan W. <jf...@tp...> - 2007-03-17 12:27:49
|
baadf00d is (I believe) what the runtime library functions in msvcrt.dll set uninitialized memory to. As for commode.obj, its sole purpose is to set the variable that is exported from msvcrt.dll as both _commode and __p__commode to some value. |
From: Greg C. <chi...@co...> - 2007-03-17 13:57:39
|
On 2007-3-17 12:36 UTC, Jonathan Wilson wrote: > baadf00d is (I believe) what the runtime library functions in msvcrt.dll > set uninitialized memory to. > > As for commode.obj, its sole purpose is to set the variable that is > exported from msvcrt.dll as both _commode and __p__commode to some value. Thanks. I guess this function is the msw parallel to posix fsync(): http://msdn2.microsoft.com/en-us/library/17618685(vs.80).aspx | The _commit function forces the operating system to write | the file associated with fd to disk. int _commit(int fd); // fd = file descriptor Would it make sense to add this to our <unistd.h>? It's not minimalist, but it can be useful; I'd volunteer to write a patch along these lines: _CRTIMP int __cdecl _commit(int); // Alternative: #include <io.h> int fsync(int __file_descriptor); __CRT_INLINE int fsync(int __file_descriptor) { return _commit (__file_descriptor); } |
From: Brian B. <br...@da...> - 2007-03-18 01:45:32
|
Greg Chicares wrote: >On 2007-3-17 0:53 UTC, Brian Bruinewoud wrote: > > >>Greg Chicares wrote: >> >> >[...] > > >>The program still aborts at the same place (according to my tracing via >>lots of print statements) and now works perfectly in the debugger (does >>what I want when I want). >> >> >A wild guess: maybe it's writing through a pointer that isn't >initialized to point to memory the program owns, but with gdb >it gets initialized to point somewhere that just happens not >to be owned by any other program? > > Possible, but I thought GCC was quite good at static analysis of what is or isn't initialised? >>drmingw doesn't do anything. It works for the test programs, but not for >>mine. When I said that my code dies without error messages anywhere, >>that includes not showing the "<program> has encountered a problem and >>needs to close." dialog box from windows with the 'Debug' but. >> >> >It has rarely told me anything useful. But when it does, it's >magical. And it costs so little to use. > > Well, for me it doesn't even notice my program crashed. >>If you didn't know what to expect the program to do you'd think that it >>worked, however, looking at my trace log file, I can see that it hasn't >>even run the destructors that it should. >> >> >I kept a log of problems I had that were like this. I found >they mostly arose from using 'new' and 'delete', so I stopped >managing memory in the application layer, and pushed it into >a library layer (e.g., smart pointers) that's guarded with >copious unit tests. And wherever possible I used the stack >instead of the heap (I had lots of code from the 16-bit era >that used the heap promiscuously, to avoid the 64K limit), >and the C++ standard library instead of C-style code (e.g., >std::string instead of new char[whatever]). I never had a >large number of memory problems, but FWIW with these >techniques I have far fewer now. > > I'll check, but there are only two instances of new and they're each called only once. And I know they're called because the are creating objects with constructors that I know have run. Other than that, everything is stack based. >>>If this is C++ and you suspect a problem with the way the >>>standard library is used, you could rebuild from scratch >>>with the warning macros defined. >>> >>> >>What 'warning macros' are you referring to? >> >> > -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_GLIBCXX_CONCEPT_CHECKS > -D_GLIBCPP_DEBUG -D_GLIBCPP_DEBUG_PEDANTIC -D_GLIBCPP_CONCEPT_CHECKS > -D_GLIBXX_DEBUG_PEDANTIC > >They've varied between versions, but it seems harmless to >specify all variants. > > > Woah. They created lots of output. I'm getting concept related errors in a third party header file (luabind which uses boost) How do I read this: ...include/c++/3.4.2/bits/boost_concept_check.h: In instantiation of `__gnu_cxx::_SGIAssignableConcept<luabind::detail::method_rep>': ...include/c++/3.4.2/bits/stl_list.h:390: instantiated from `__gnu_norm::list<luabind::detail::method_rep, std::allocator<luabind::detail::method_rep> >' ...include/c++/3.4.2/debug/list:45: instantiated from `__gnu_debug_def::list<luabind::detail::method_rep, std::allocator<luabind::detail::method_rep> >' ../../../Include/luabind/detail/class_rep.hpp:373: instantiated from here ...include/c++/3.4.2/bits/boost_concept_check.h:216: error: `__gnu_cxx::_SGIAssignableConcept<_Tp>::__a' has incomplete type ../../../Include/luabind/detail/class_rep.hpp:65: error: forward declaration of `struct luabind::detail::method_rep' This code existed, and worked, prior to the changes i made that have caused the current problem. Shouldn't this be a compilation error rather than a runtime error? You can't instantiate a template with an incomplete type so this seems weird. The other one I get is: ...include/c++/3.4.2/bits/boost_concept_check.h: In member function `void __gnu_cxx::_SGIAssignableConcept<_Tp>::__constraints() [with _Tp = luabind::detail::method_rep]': ...include/c++/3.4.2/bits/stl_list.h:390: instantiated from `__gnu_norm::list<luabind::detail::method_rep, std::allocator<luabind::detail::method_rep> >' ...include/c++/3.4.2/debug/list:45: instantiated from `__gnu_debug_def::list<luabind::detail::method_rep, std::allocator<luabind::detail::method_rep> >' ../../../Include/luabind/detail/class_rep.hpp:373: instantiated from here ...include/c++/3.4.2/bits/boost_concept_check.h:208: error: `__a' undeclared (first use this function) Again, it seems weird. Given that the code was working earlier, are these ignorable? I get the same errors whenever I include the luabind header file, regardless of whether I actually instantiate any template from there. That is, I am not instantiating a luabind template with an incorrect class type in at least one case (becuase I'm not instantiating anything) and I get the same errors regardless. >>>Aside from that, you can step through everything with a >>>debugger (where the problem will be difficult to observe), >>>or add print statements to localize the problem (running >>>it outside the debugger). >>> >>> >>Print statements always finish at a particular function, but the last >>batch of output may not have been properly flushed to the disk... >> >> > >Good point. There's some msw function that's supposed to >flush all buffers to disk...let's see...okay, it's >_flushall(), but you have to link 'Commode.obj', which >I guess requires ms tools. > > > An 'easier' way is to close the file everytime you finish writing to it. A lot slower, but 100% guaranteed (unless you crash the OS itself). I'll change the tracing code to do this. >>I'm using -Wall and -Wextra and the only errors I get are unused >>function parameters. Should any other warnings be enabled? >> >> >Here's the complete set I use. > >[...snip...] > > I added them all in, and other than lots of undefined macros in if statements (-wundef) which are all in luabind and boost and a couple of other warning in there as well (unused parameters), there was nothing. (Which is quite pleasing, really). Thanks for your help so far. - Brian |
From: James S. <jam...@op...> - 2007-03-18 07:43:13
|
On Sun, 2007-03-18 at 12:45 +1100, Brian Bruinewoud wrote: > Greg Chicares wrote: > > >On 2007-3-17 0:53 UTC, Brian Bruinewoud wrote: > > > > > >>Greg Chicares wrote: > >> > >> > >[...] > >>Print statements always finish at a particular function, but the last > >>batch of output may not have been properly flushed to the disk... > >> > >> > > > >Good point. There's some msw function that's supposed to > >flush all buffers to disk...let's see...okay, it's > >_flushall(), but you have to link 'Commode.obj', which > >I guess requires ms tools. > > > > > > > An 'easier' way is to close the file everytime you finish writing to it. > A lot slower, but 100% guaranteed (unless you crash the OS itself). > I'll change the tracing code to do this. A much nicer way to capture debuggery strings I find is to use the ol' OutputDebugString(). It ensures that the a string is written to the debugger before returning, and if there is no debugger listening it incures little overhead to leave the debuggery in. I still usually #ifdef DEBUG ... #endif to build a release version. Regards, James. |
From: Tuomo L. <dj...@ik...> - 2007-03-20 17:25:56
|
Brian Bruinewoud wrote: >>I kept a log of problems I had that were like this. I found >>they mostly arose from using 'new' and 'delete', so I stopped >>managing memory in the application layer, and pushed it into >>a library layer (e.g., smart pointers) that's guarded with >>copious unit tests. And wherever possible I used the stack >>instead of the heap (I had lots of code from the 16-bit era >>that used the heap promiscuously, to avoid the 64K limit), >>and the C++ standard library instead of C-style code (e.g., >>std::string instead of new char[whatever]). I never had a >>large number of memory problems, but FWIW with these >>techniques I have far fewer now. > > I'll check, but there are only two instances of new and they're each > called only once. And I know they're called because the are creating > objects with constructors that I know have run. Other than that, > everything is stack based. Have you tried adding _heapchk() statements? http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_crt__heapchk.asp -- Tuomo ... All that glitters have a high refractive index |
From: Brian B. <br...@da...> - 2007-03-31 07:33:27
|
Brian Bruinewoud wrote: >Hi, > >I'm trying to debug something. When I run the program normally, it >'dies' (no error message anywhere and my trace statements just suddenly >stop). So I pulled out good ol' gdb, but the program 'works' there (ie, >it doesn't die). The only reason I can think of is that gdb makes >uninitialised memory more palatable to the bug in my program. So I want >to know is 'baadf00d' a gdb magic number or is it a microsoft >(specifically, DirectX DirectInput) thing? > >Thanks, >Brian. > Problem solved, I was indexing a std::vector out of range :-) oops. |