|
I have a debugging situation I've never really encountered before, and, thinking ahead, a similar situation will probably arise after my thing is in beta. So, what's going on is that I have a multithreaded networked game, in Windows. In order to test the network stuff I obviously have to run (at least) two instances. That means one under the debugger and one not. If I put a breakpoint in the debugger one, the other one crashes. That's fine and expected at this stage, and I could probably find the problem and fix it without too much effort, but it leads to my question - how do you make it so a program running not under the debugger will, upon crashing, dump a state that can be used to find the error? Once it's in beta I'm sure other people will find ways to crash it, and I'd really like reports to be more useful than "hey it crashed when I did something". Ideally automatic crash reports, but I'm not willing to do it the Windows way that appears to require an annual $500 payment to Verisign. It looks like SetUnhandledExceptionFilter would be the way to go about this, and possibly MiniDumpWriteDump, but I'm having trouble finding a coherent "here is how to get the file and line number of your crash". (I'm assuming I could either include the debug info with beta versions, or have the dump provide something that can be sent to me and can then be cross-referenced against the debug info generated by Visual Studio to give a file and line number.) tldr; how do you make a program crash-dump info in a form that can be turned into a file and line number (and ideally but not necessarily also stack trace)?
|
# ¿ Aug 22, 2010 23:36 |
|
|
# ¿ Apr 28, 2024 15:19 |
|
pseudorandom name posted:http://code.google.com/p/google-breakpad/ I even saw that mentioned in the "how does your company do bug reports" thread, but it was mentioned amongst such contenders as Bugzilla so I didn't parse it as being an auto-reporting thing. Cheers. Edit: what the gently caress is all this bullshit with having outdated install instructions -> now requiring gyp contrary to instructions -> which in turn has poo poo install instructions -> requires python. I'm sure this is all perfectly fine in Linux but in Windows it's no fun at all. Oh, and both gyp and breakpad only downloading with svn, so there's another stupid requirement too. roomforthetuna fucked around with this message at 02:45 on Aug 23, 2010 |
# ¿ Aug 23, 2010 01:27 |
|
Just a little update - Google Breakpad sounded like just what I was looking for in crash-debugging, but it turns out it's recently been modified to make it a massive pain in the arse to get working in Windows, to the point that I'd now rather modify this guy's thing and add file-dumping, uploading and pdb cross-referencing myself. (Edit: on second thought, that basically leaves nothing of that guy's thing, so I might as well just write my own from scratch. It looks pretty easy now that I've found all the functions I need.) It really should just be a case of "get exe, lib and headers" (the exe would be the uploader app), or "get source, build projects, use those exe, lib and headers", but instead there's a crazy song and dance required to even get the source and project files ready, and then when I finally managed that, the compilation failed, unable to find one of its own header files, having an undeclared variable, and a couple of buckets full of deprecated function warnings. In summary, gently caress cross-platform open source libraries that are still in development and don't have a clear "latest stable version" option. roomforthetuna fucked around with this message at 02:50 on Aug 25, 2010 |
# ¿ Aug 25, 2010 02:45 |
|
floWenoL posted:NIH syndrome strikes again! NIH syndrome is "everyone else's stuff sucks so I'll do it all myself", this was "only this one library allegedly does what I want, and it, specifically, sucks." (Admittedly I do feel that way almost every time I try to use a third-party library for anything, but it's not because I object to third-party things, it's just that I object to libraries that don't actually save me work!)
|
# ¿ Aug 26, 2010 01:34 |
|
Well, I do only need a small part of the functionality (I don't need any of the cross-platform stuff, which potentially reduces the 'dump' part to a single API function call, for example), and I already need to deal with some HTTP stuff so I'd be better off uploading the dump file with my existing HTTP stuff than including a second one, which is also better when it comes to the server-side because I won't need to deal with integrating their server-side stuff (if there even is any in the library). There certainly isn't a good reason (from a library-user perspective) why the library would be a pain in the arse to download and then not actually compile once downloaded. So I'm safe from the "there WAS a good reason for the retarded way of doing things" problem. (I'm sure there is a good reason for it not compiling and having outdated documentation from an open-source developer perspective, such as "some fucker uploaded an update into the version control system that broke things and it didn't get fixed yet", but that doesn't make it worthwhile from the perspective of someone who wants to use the library.) Edit: and it doesn't always look that way at first, I've been perfectly satisfied with eventlib (on the Linux side), libjpeg, libtomcrypt and zlib, for example, with no temptation to write my own. roomforthetuna fucked around with this message at 04:16 on Aug 26, 2010 |
# ¿ Aug 26, 2010 04:13 |
|
floWenoL posted:There will be always some effort necessary to get third-party libraries working. And it's not really a case of "it seems better to do it yourself because you see progress" - it took me about 20 minutes to implement the main 'crash-dump' part in a way such that it applies throughout my project, and I expect similar for the 'upload' part when I get to it. I already spent longer than that trying to get Breakpad to compile. If, after all this reasoning, it's still a case of NIH syndrome, then good, I guess. vvvv Wasn't citing him as an authority or anything (I don't even know who it is), just a summary of the point that if it's still NIH syndrome when it actually is faster and easier and possibly more effective to write it yourself, then in those cases NIH syndrome is good. The alternative is that this wasn't a case of NIH syndrome. Unless you'd like to argue that slower, harder and worse is good. roomforthetuna fucked around with this message at 17:17 on Aug 26, 2010 |
# ¿ Aug 26, 2010 16:47 |
|
Mustach posted:It's an open source project; have you considered fixing it and submitting a patch? (Keep in mind that this is a question and not an accusation.) Also, the last time I tried looking into patching an open source project it was Firefox. That vomitpool of code has put me off ever doing anything with open-source code other than "compile it".
|
# ¿ Aug 26, 2010 18:32 |
|
Gangsta Lean posted:roomforthetuna, have you looked at bugtrap? I acknowledge that this time I really am pulling an NIH syndrome - I want it done my way, and the pre-existing solutions just don't have quite enough options to make it that way. (I'm planning on dumping the crash report to a file, triggering a separate "ask and send the report" program, then finishing the crash-out from the main program so DirectX will drop its greedy control of the screen. And for the sending, a simple HTTP file-send so I can just receive the report with any webserver and a tiny amount of script.)
|
# ¿ Aug 27, 2010 02:11 |
|
Longer version of OddObserver's explanation - "Test t = Test(1)" could potentially go two ways - in this case it's being treated as identical to "Test t(1)", as an initialiser not an = operator. It could also be treated as identical to "Test t; t = Test(1);" which would require a constructor with no parameters to exist, and then would act more like the other lines. So at this stage you've done basically "Test t(1)", t.n is 1, and the constructor has been called with 1, for that output. "t = Test(2)" - this makes a temporary 'Test' object and then uses the = operator, which, not having been explicitly defined, I believe acts like "t.n = temporary.n" for every member variable. So you get constructor 2 and destructor 2 called for the temporary object, and t.n is now 2. "t = Test(3)" - does the same thing, so you get constructor 3, destructor 3, and t.n is now 3. Then you hit the return and go out of scope - t is destroyed, the destructor is called and outputs t.n, so you get your second "destructor 3". Edit: Am I correct for what the default = operator does, such that member objects' overloaded = operators would be called, or does it just act like a memcpy? It's never really come up for me that I'd be using it and there'd be a difference. roomforthetuna fucked around with this message at 02:24 on Aug 28, 2010 |
# ¿ Aug 28, 2010 02:22 |
|
Dooey posted:I profiled it :P stack.top() is used extensively in one of my functions, and within that function it takes up 47.1% of the time in that function. No other line in the function takes more than 8.5%. I can change the algorithm slightly, but at a cost of reduced accuracy. I will try a vector though, and see how it compares. __asm mov ax,bx look like a bottleneck, after all.
|
# ¿ Sep 14, 2010 04:07 |
|
Jan posted:The compiler most likely optimises the empty constructor call anyway. You're mostly losing terseness and clarity for... no advantage at all.
|
# ¿ Sep 16, 2010 02:57 |
|
epswing posted:Let me simplify my question. Say I have two programs connected by a pipe. I wish to send some xml/json/etc data from one program to the other. The receiving program needs to do something with this bundle of data, which I'll call a "message". The receiving program loops over ReadFile, filling a buffer with whatever comes down the pipe. For my things, I like to start each message with a message size, so you know how much data you need to accumulate. Since I do games, I don't want to block, I make my sockets or pipes state-machines with states "connecting", "waiting", "partialmessage", "disconnected". Then for each check it goes something like code:
|
# ¿ Sep 17, 2010 20:42 |
|
epswing posted:Neato, like Content-Length in HTTP. Having a binary message size header is certainly more efficient and simpler than reading to a delimeter (and easier than HTTP's Content-Length header because with HTTP you still have to read the header itself with delimeters before you can do a big known-size data burst), though data in binary also carries its own can of worms (byte orders if you're not sure you're sticking with one OS/hardware, and it's not good for readability/debugging).
|
# ¿ Sep 17, 2010 21:39 |
|
pseudorandom name posted:And you have to keep in my that whomever is sending the message could be lying about the buffer size. vvvv Yeah, I did say you need a way to pre-emptively shut a blocking thread down if it's threaded. If it's not threaded or blocking, per my pseudocode, then a lack of data can't cause a hang. That's not just an issue with false sizes though, it's also an issue with clients crashing, and just as much of a problem either way if you use delimeters (malicious client can stop sending data without sending a delimeter). roomforthetuna fucked around with this message at 21:00 on Sep 18, 2010 |
# ¿ Sep 18, 2010 19:48 |
|
Isn't a compiler supposed to deal with dividing a constant by another constant such that it doesn't end up in the assembler code? (Like the turkey said but the assembly listings don't reflect.) I would have thought that would be the case even in non-optimised builds.
|
# ¿ Sep 28, 2010 21:15 |
|
epswing posted:Edit: or maybe...should my prototype be void Read(std::string& s)?
|
# ¿ Sep 30, 2010 18:44 |
|
Mopp posted:edit: the problem remains, there's an error in the code up there since it manages to enter the if(ispunct(is.peek())), but temph remains 0.
|
# ¿ Sep 30, 2010 21:51 |
|
OddObserver posted:To elaborate, I am pretty sure you can't accurately represent numbers as simple as 0.10 (e.g. 10 cents) in (binary) floating point. Maybe not necessarily 100 for some currencies, but whatever, currency can always be stored as an integer number of whatever the smallest unit of currency is. So when England still had half-pennies it could have been output as (money/200) + "." + ((money%200)/2) + ((money%2)?" and a half penny":"") (You'd probably want to use a 64-bit integer, since $43M isn't a very high limit, but 184 quadrillion dollars should work out okay. Or 92 quadrillion if you're allowing negatives.) As an example of floats losing precision at higher numbers: code:
code:
Edit: Also, if you add one or two pennies to a million, it's just flat lost. roomforthetuna fucked around with this message at 02:20 on Oct 1, 2010 |
# ¿ Oct 1, 2010 02:18 |
|
ehnus posted:Is it possible to override new/delete/malloc/free/etc. so that they capture a callstack (or partial callstack) for every allocation and then have it log what wasn't cleaned up on exit? It goes something like this: code:
I also have a "DebugStart()" function that sets up the recording structure, and "DebugEnd()" that outputs all the stuff, though you could do that with a global object's constructor and destructor instead. The one gotcha I found with this setup is that if you allocate stuff in the constructor of a global object (ie. before 'main') or destroy it in the destructor of a global object (ie. after 'main' ends) then it's not good. (Also, make sure you don't have the #define'd new/malloc being used for allocation within your logging stuff, you don't want it to start logging itself.) roomforthetuna fucked around with this message at 08:10 on Oct 1, 2010 |
# ¿ Oct 1, 2010 05:47 |
|
Ledneh posted:Would I also need to #define delete and delete[] to RFree as you did with free?
|
# ¿ Oct 1, 2010 17:00 |
|
Ledneh posted:Okay, thanks. I've almost got this stuff working, except for one thing: the #define new new(__FILE__, __LINE__) breaks placement new, which I need to work because I use boost::unordered_map. What should I do to be able to use this define while still allowing placement new? You can make that a bit more flexible by doing the original new-redefinition like code:
code:
|
# ¿ Oct 1, 2010 22:35 |
|
Ledneh posted:roomforthetuna, I got that one fixed (and without modifying boost--modifying code that isn't our company's is a nono around here) except now some of the oracle headers we use have classes that provide their own operator new, and that's broken it again.
|
# ¿ Oct 1, 2010 23:05 |
|
Rocko Bonaparte posted:Now I have a problem where I can't do things like an array subscript operator straight off the pointer. For now, I implemented a get() for an unchecked access, versus at() which I believe is STL's way of doing a bounds-checked access. But I do like being about to subscript. Is there a good way to have the smart pointer while being able to subscript?
|
# ¿ Oct 4, 2010 19:14 |
|
More to the point from what pseudorandom name said, it's not even a pointer to a VariableTable, it's an uninitialised pointer to type VariableTable. If you have a preexisting table you want to point to, then T=&othertable; If you are wanting to make a new table then T=new VariableTable; (And then you'll also need to delete T;, or whatever pointer ends up storing that address, at some point.)
|
# ¿ Oct 12, 2010 20:42 |
|
In that case, the answers to your questions in no particular order are pretty much: 1. There is no string, there is only arrays of chars. 2. Any string literal in quotes has an automatic '\0' on the end. 3. For a reference of library functions related to strings, you just need to look at what's in string.h and, from stdio.h, the printf and scanf series of functions. Those are the only ways C considers 'strings' at all, though they are still really just arrays of chars.
|
# ¿ Oct 17, 2010 04:20 |
|
drcru posted:It doesn't seem to be updating the value of seats_available The "originally" method in the comments is closer to actually updating the value.
|
# ¿ Oct 19, 2010 16:13 |
|
drcru posted:I changed it back to how it was originally now but it still only seems to deduct it from seats_available once... Any ideas on what I did wrong? Though even if it was working as you'd expect, you'd still need some sort of locking anyway, or you risk all 6 processes first reducing the number, then the same reduced number (30) being piped 6 times. Here is someone talking about how to do shared data between forked processes. If you can do it with posix threads, that'd probably be better suited to your task, really, since they share all the memory already so you'd only need to deal with the locking. But seriously, first do the printing information trick to find out what's going wrong with your version, don't just blindly do it someone else's way.
|
# ¿ Oct 19, 2010 20:38 |
|
Jose Cuervo posted:There is no way to exit the function without executing the delete line, so I don't understand how this is leaking memory. Post the function. Edit: It's weird that you're changing 'new' to a call that passes the file and line number from which it is called, but the debug information you get back about the leak doesn't include the file or line number. roomforthetuna fucked around with this message at 20:13 on Oct 25, 2010 |
# ¿ Oct 25, 2010 20:10 |
|
Jose Cuervo posted:To answer the poster below you, I tried to get the file and line number information to appear as suggested on the msdn page, but I was unable to make it work. I tired some of the community suggestions posted but they only made the file name and line appear if the memory leak occurred in my main.cpp file.
|
# ¿ Oct 25, 2010 21:08 |
|
slovach posted:Also I was thinking, is there even a point to the inline keyword any more? The compiler has an option where it will inline whatever it deems fit regardless of the function being marked as inline or not.
|
# ¿ Oct 29, 2010 04:01 |
|
Dwayne Bensey posted:Okay, took all that into account; changed (letter=='A'||'B') to ((letter=='A')||(letter='B')), and used an if-else if ladder in a "do while" loop. Tried using a switch statement at first but I wasn't really sure how to get it to repeat itself and ask me for another letter. It worked anyways, so I guess that's the important thing.
|
# ¿ Oct 29, 2010 16:36 |
|
boak posted:why is this causing me a segfault??
|
# ¿ Nov 4, 2010 16:16 |
|
Mustach posted:Are you verifying that nsd != -1 before trying to print the address?
|
# ¿ Nov 4, 2010 17:17 |
|
boak posted:on the printf() - if I comment it out theres no segfault and the program continues along its merry way. code:
code:
|
# ¿ Nov 5, 2010 16:24 |
|
boak posted:now segfaulting on printf("%s",tmp); code:
Try code:
Try running it under a debugger so you can look at the variables' states after if crashes? (gdb is pretty useful but not much fun interface-wise. Worth learning though if you're going to be command-line programming much.)
|
# ¿ Nov 5, 2010 18:15 |
|
A remarkably specific server-programming question - I have a server that loads extra functionality from plugins. The base server code is pretty tight, full of plenty of user-data integrity checks and such. The plugins also should be, but there's probably going to be a lot of them and likely written in haste, so I don't want to be relying on them being bulletproof, and I don't want a bad function crashing the whole server. (It's basically a MMORPG server, so crashing out is not acceptable behaviour for it.) Is there a decent way of doing this? I don't need plugins to be sealed in an indestructible sandbox, since it'll be my own code, I don't need to protect against maliciousness - I just want it to fail gracefully if I have a bad function. It's most likely that if they explode it'll be from something like trying to access a null pointer, or an unsigned array index accidentally going to 0xffffffff, Is there a decent(ish) way to do this? Maybe something like trapping SIGSEGV and throwing an exception from there, and wrapping plugin function calls in a "try {function} catch (...)"? (This is on a Linux system.)
|
# ¿ Nov 6, 2010 02:00 |
|
Vanadium posted:Write the plugins in lua
|
# ¿ Nov 6, 2010 02:50 |
|
Duke of Straylight posted:Yeah, sigaction(2) (though you probably know more about how to use it than I do). Might have to be careful if you're combining multithreading with signals, and don't forget that SIGFPE, SIGILL, SIGSEGV and etc. are just a small part of the ways code could go wrong - you could still be hosed over by resource leaks, poor performance or nontermination, memory corruption... so if you do implement this level of protection, better not advertise it so people won't think they can depend on it. roomforthetuna fucked around with this message at 20:28 on Nov 6, 2010 |
# ¿ Nov 6, 2010 17:31 |
|
Just in case someone else was interested in the idea, it turns out that sigaction won't really help with recovering after a SIGSEGV - you can't throw an exception from inside the signal handler, nor do anything that will take you back to a relatively safe point in the code, except by crazy horrible direct stack pointer manipulation. So it seems I'm stuck with either "rewrite everything so I can use some sort of scripting language for the plugins" or "just write the dynamic plugin functions even more carefully". Who'd have thought I'd wish for something like Microsoft's __try and __catch.
|
# ¿ Nov 7, 2010 22:31 |
|
|
# ¿ Apr 28, 2024 15:19 |
|
Duke of Straylight posted:setjmp() and longjmp() maybe? Or sigsetjmp() and siglongjmp(), it appears that Wikipedia warns about using setjmp() and longjmp() together with signal handling.
|
# ¿ Nov 8, 2010 01:36 |