Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
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)?

Adbot
ADBOT LOVES YOU

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
Thanks, that looks like pretty much what I was looking for (and also suggests that the way I was thinking of implementing it was right, hooray!)

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

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
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

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

floWenoL posted:

NIH syndrome strikes again!
Hey, that's not fair, I was perfectly willing to use a third-party library that did what I wanted. It just sucked and turned out to be more work to get it working than making it myself would be.

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!)

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
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

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

floWenoL posted:

There will be always some effort necessary to get third-party libraries working.
But there's a big difference between "some effort to get it working" and "it's actually broken at the moment". If it doesn't even compile then there's a good chance there's going to be runtime bugs too, especially when a library is still in active development. If there was a "last known stable" version (maybe there is - I should say if there was a last known stable version clearly marked as such and readily available) then I'd have put in more effort to get it to work, but fixing something that's actively broken in a library that there's a good chance you're also going to have to update to newer versions (that may also require fixing again) is not just "some effort to get it 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

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.)
Briefly. But the point of using the library was to save me a little work on my project, not to suck me into a whole different project where I'd come in with no idea what anything does, spend days learning about it, and then eventually have my patch rejected because I didn't understand their peculiar cross-platform implementation/philosophy.

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".

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Gangsta Lean posted:

roomforthetuna, have you looked at bugtrap?
I hadn't, and thanks for the recommendation - it looked really good until I got to the options for the delivery of crash reports, which appear to be too Windows- or Java-dependent for my setup (my server is all Linux and no Java). I also foresee a problem with crashes while in DirectX full screen mode trying to pop up a "do you want to report this error" dialog box - dialog boxes and DirectX full screen frequently not playing well together. Even then, it still looks pretty good, and well documented, and set up to be pretty easy to use. I am tempted. It's a big improvement over the terrible docs for Breakpad.

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.)

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
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

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.
Perhaps that function is actually taking very little of your program's time? 47.1% of next to nothing is still next to nothing. Or perhaps it is just a really not-doing-very-much function that's called many many times? With a short enough function called enough times you can make even
__asm mov ax,bx
look like a bottleneck, after all.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Jan posted:

The compiler most likely optimises the empty constructor call anyway. You're mostly losing terseness and clarity for... no advantage at all.

Now if the destructor was virtual, you'd have a bit more reason to leave an empty base one, but this is not the case.
Note that if the destructor was virtual the compiler most likely wouldn't optimise the empty destructor call away.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.

In the case that a message is larger than the buffer, and is split across several calls to ReadFile, how would you (A) accumulate and put together the message (which you need to do before processing it) and (B) differentiate between messages?

Am I thinking about this entirely the wrong way?
If the receiver needs to still respond to other things, then you need a global/static/heap buffer you can collect the message into, which you keep filling until you have a while message. If the receiver can just wait until the message is complete or the connection breaks, then you can just use a blocking read of the appropriate size, if you know in advance what the appropriate size is.

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:
if (state==waiting) {
  try to read a message size
  if I got one, change state to partialmessage, currentpos to sizeof(size)
     change target size to the size, and stick that size so far in the buffer
}
if (state==partialmessage) {
  try to read (targetsize-currentpos) into the buffer
  if it's done, deal with the now complete message then state=waiting, currentpos=0
  if I got some but not enough, update currentpos
  if the connection dropped, disconnect
}

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

epswing posted:

Neato, like Content-Length in HTTP.

Also, I spin off a thread for reading, which blocks in a loop until there's stuff to read. I think that will work for my purposes.
Yeah, using blocking functions can make the reading loop a lot easier, though multi-threading comes with its own can of worms of course. Make sure you critical-section the code where you stack and unstack your completed messages, and have some way to end the thread cleanly.

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).

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

pseudorandom name posted:

And you have to keep in my that whomever is sending the message could be lying about the buffer size.
Only to the point of "if the message is ridiculously large then just drop the connection". Other than that a false size is no problem - obviously you'll want to validate all the messages anyway though, and size can be a contributor. But if you get a 'size' that says 20 bytes and the message is 500 bytes, that won't be a buffer overflow or anything, it'll just be a crap busted message 20 bytes long followed by a nonsense-data 'size' of the next message taken from the middle of 500 bytes.

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

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
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.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

epswing posted:

Edit: or maybe...should my prototype be void Read(std::string& s)?
You'd want bool Read(std::string& s) if you're going to do it that way - you still want a return value to check for end condition.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.
That's what Grazing Occultation said was happening - it enters that because ".50" "ispunct"[uation], but then you try to get the integer from the string ".50", which isn't an integer, because integers don't begin with a "." - you have to strip that off after the punctuation is matched and before you try to read an integer.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.
You'd get the occasional rounding error up or down a cent, yeah. Also, more importantly, you'd lose precision at larger numbers, and there's really no reason at all not to just store money as a single integer representing cents, which you can print as (money/100) + "." + (money%100).

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:
 float x=100000.00f;
 x+=0.01f;
 printf("%f\n",x);
 x+=0.01f;
 printf("%f\n",x);
 x=100000.00f;
 x+=0.02f;
 printf("%f\n",x);
Outputs
code:
100000.007813
100000.015625
100000.023438
Yeah, 1 penny plus 1 penny = 1.5625 pennies, but 2 pennies = 2.3438 pennies!

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

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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?
Not sure if you mean this question as "in his situation" or "in general". In general, yes, it is certainly possibly, because I have a little library I use for all my debug code that does a simplistic version of that (as well as doing the same thing for most of the common Windows resource allocation/deallocation pairings, like CreateBitmap etc.)

It goes something like this:
code:
void * __cdecl operator new[](size_t size,LPCTSTR fname,int line) {return RMalloc(size,fname,line);}
void * __cdecl operator new(size_t size,LPCTSTR fname,int line) {return RMalloc(size,fname,line);}
void __cdecl operator delete[](void *p) {RFree(p,_T(__FILE__),__LINE__);}
void __cdecl operator delete[](void *p,LPCTSTR fname,int line) {RFree(p,fname,line);}
void __cdecl operator delete(void *p,LPCTSTR fname,int line) {RFree(p,fname,line);}

#define new new(__FILE__,__LINE__)
#define malloc(sz) RMalloc(sz,__FILE__,__LINE__)
#define free(p) RFree(p,__FILE__,__LINE__)
Then RMalloc records the filename, line number and allocated address (indexed by the address) then returns a standard malloc of the size, and RFree erases the entry with the given address and performs a standard free, or outputs the file and line number in which you tried to free something that wasn't in the list.

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

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Ledneh posted:

Would I also need to #define delete and delete[] to RFree as you did with free?
No - note I also didn't #define new[], just new. Just making alternative new/delete functions automatically overrides the default - the only reason an alternative new is #defined is so that 'new' with a line number and filename is called. The reason two 'delete' functions are written, both calling RFree? I forget precisely, but there's some context in which the 'delete' that matches the 'new' is called (ie. the delete with a line number and filename), and other contexts in which a normal delete is called. #define-ing the deletes didn't work out when I tried it. Luckily RFree doesn't really need a line number or filename to work.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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?
What I did for that, a bit lazily, was just #undef new before doing a placement new, and then redefining it afterwards.
You can make that a bit more flexible by doing the original new-redefinition like
code:
#define DEBUG_NEW new(__FILE__,__LINE__)
#define new DEBUG_NEW
Then around your placement new
code:
#ifdef new
#define MUST_RESTORE_NEW
#undef new
#endif

(your placement new code here)

#ifdef MUST_RESTORE_NEW
#define new DEBUG_NEW
#undef MUST_RESTORE_NEW
#endif

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.
Ah, yeah, that would screw it up. Don't know how I'd work around that, luckily it hasn't come up for me.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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?
I think if you want to use operators and you have a pointer, you have to dereference it. ie. you can't do arraypointer->[5], but you can do (*arraypointer)[5].

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
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.)

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
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.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

drcru posted:

It doesn't seem to be updating the value of seats_available
Where do you expect it to update that value? It copies it into "seats_open" and then only updates seats_open.

The "originally" method in the comments is closer to actually updating the value.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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?
Is seats_available a global variable? Are all the processes using the same one? If I was debugging this I'd try outputting the address alongside the value. (I know the answer to this, but how to figure it out is a more important lesson than the answer.)

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.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.

Any help please?
My guess would be (assuming everything else you've said is accurate) that somewhere in that function you do something that changes 'nb' such that when the delete line is called it doesn't have the same value so the delete fails.

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

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.
That's because you only have the "#define new [...]" stuff at the start of main.cpp - you want to put that at the start of every cpp file (perhaps after header includes) to get that effect everywhere. (That whole block you posted, not just the one line.)

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.
One use for inline that I enjoy (though it's probably not good software engineering) is as a way of making a very small member function exist across several DLLs without having to export-link it or have it be virtual. If you just put the function in the header normally then you must only include it once, on pain of errors, but if it's declared inline then you can have the same definition multiple times without causing a problem.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.
Thanks guys! :)
Switch doesn't repeat, it's basically an "if-else" ladder that has the capability to optimise better and is more readable. It would repeat the exact same way your if-else ladder does, via your "do while" loop.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

boak posted:

why is this causing me a segfault??
My guess is maybe cli_addr is not as big a structure as it needs to be? Is it a struct sockaddr_in? Did you initialise cli_addrlen with sizeof(cli_addr)?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Mustach posted:

Are you verifying that nsd != -1 before trying to print the address?
Worth doing but I don't think it could be the problem, since any value in the addr is valid enough to print. Is the segfault in the printf or in the accept (or even sooner?)? Have you checked that sd is a valid socket descriptor before calling accept?

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

boak posted:

on the printf() - if I comment it out theres no segfault and the program continues along its merry way.

any other ideas?
Split it up more for debugging purposes! Is the crash in inet_ntoa or in printf?
code:
printf("Client connected: %s\n", inet_ntoa(cli_addr.sin_addr));
becomes
code:
char *tmp=inet_ntoa(cli_addr.sin_addr);
printf("Client connected: ");
fflush(stdout); //fflush just to make sure you don't think the crash is somewhere it isn't
printf("%s",tmp); //used printf in case that was causing the crash, coulda used puts
fflush(stdout);
printf("\n");

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

boak posted:

now segfaulting on printf("%s",tmp);
Try
code:
puts(tmp);
in place of that line?
Try
code:
printf("%x",tmp);
to check if inet_ntoa is returning null or something?
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.)

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
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.)

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

Vanadium posted:

Write the plugins in lua :)
That actually seemed like it might be a good idea, but from a quick glance it looks like I'd not have a lot of fun trying to make my way through complex 'struct' data inputs to the plugins nor calling back into virtual functions off a global pointer from inside a Lua script.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.
Right, as I said it's just for my own code, as a way to make dynamic changes a bit more robust. The chances of accidental wide-scale memory corruption are much much smaller than the chances of an accidental division by zero or bad pointer. I can't realistically do most of the other suggestions, since the plugin functions will be needing access to the global data, so all I'm really looking for is a "break out of the function instead of crashing" protection, not a full-scale most-robust-possible option. (While that would be nice, it would be so much more work to implement that way that it's not worth it.)

roomforthetuna fucked around with this message at 20:28 on Nov 6, 2010

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!
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.

Adbot
ADBOT LOVES YOU

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

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.
Thanks, sigsetjmp and siglongjmp seem to be almost doing what I was hoping for - it's fighting with libevent a bit, and seems to not actually restore the stack as the manpages claim, but I can get it to just about behave, and since it's something that ideally won't be going to come up anyway, the shakiness is acceptable.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply