Re: memmove crash
- From: "Richard Cooper" <spamandviruses@xxxxxx>
- Date: Fri, 23 Sep 2005 05:13:33 GMT
On Wed, 21 Sep 2005 15:57:50 -0400, T.M. Sommers <tms@xxxxxx> wrote:
Richard Cooper wrote:
The problem with that is how do you tell valid arguments from invalid arguments?
In this particular case, you have to remember the sizes of the arrays pointed to by the two pointers, and compare the number of characters to be moved with those sizes.
Well, since we're assuming that I've already screwed up my pointer arithmetic, I don't think trying to do that will get me anywhere.
Signal handlers were not meant to be debugging tools, really.
I can't imagine what else the SIGSEGV and SIGILL signals could be used for. Surely they were intended to be used for the only thing that they're good for.
They are for terminating a program that is doing something hideously wrong.
And they're provided as an alternative to the 'kill -9' style kill, so that the program can clean up before it dies. That's how I was trying to use them. Now if it's not possible to actually do anything in the signal handler, then it might as well not even be there.
I forgot to mention that the POSIX standard and the Linux man page list the standard library functions that are safe.
There's no mention of 'signal' or 'handler' in the printf page, does that mean that it's safe?
Exactly. There is not much that can safely be done in a signal handler.
Now the interesting thing is that from assembly I can do whatever I want to inside a signal handler.
No, you can't. Calling an unsafe function from assembly does not magically make it safe.
My point was that there are no unsafe functions in assembly. In my signal handlers, I can call each and every system function without a problem. So if I want to print something to the screen, I can do that.
Now you're right that if I call an unsafe C function, then the fact that it's done from assembly language isn't going to help anything. However, in assembly language, I only make Linux system calls, and I don't use the C library, so I can do whatever I want in my signal handlers because Linux itself doesn't have this 'unsafe function' problem, it's just a libc thing.
That's why this memmove and signal thing surprised me. I'm used to there being no issues with what can and cannot be done in a signal handler.
If signal is successful, then it returns a pointer, if it's unsuccessful, then it returns an integer.
signal() always returns a pointer.
The C function signal() always returns a pointer. The linux system call signal returns a pointer on success and a negative error number on failure. The C library checks for this negative number, and then puts the negative of it (a positive number) in errno, and makes the C library signal() return SIG_ERR.
So since I was making a direct system call, without any C library interfacing between me and the kernel, making the return value an integer was the correct thing to do. However, as you've pointed out, if I had used the C library's signal(), then it should have been a pointer instead.
That is the wrong comparison to make. signal() returns SIG_ERR if there was an error, and its return value should be compared to that.
Again, the direct system call differs here. There are no kernel error codes which are specific to signal, and it, like every other function, just returns one of the standard error codes. For example, if you try to register a signal handler for signal 9, it returns -EINVAL which is -24, which is quite different than SIG_ERR which is just -1 cast to type sighandler_t, making it a positive number so that comparisons will work.
It shouldn't take more than a few seconds to check the man page.
No, but it does take more than a few seconds to, every single time I use a function, check the man page, see what header files the function needs, and then go check the mile-long list at the top of the source file to see if that one's included yet or not.
On my Linux system, you get siginfo_t when you include signal.h.
Actually my problem with siginfo_t was that I didn't know about the -> operator yet and so I couldn't access any of the structure members.
The 'duplicate definitions' thing came from trying to include "asm/siginfo.h" as I was thinking that would give me ucontext_t, but it turns out that's in "ucontext.h" anyway. The man page doesn't tell you where you're supposed to get ucontext_t from, and signal.h doesn't give it to me at least.
What's so bad about that anyway? It actually seems like the right thing to do to me.
Failing to include stdlib.h makes a call to malloc default to return an int. Pointers and ints are not the same size on all systems.
Seems like a pretty stupid default then.
That goes back to the beginnings of C. All undeclared functions were assumed to return ints.
If it's undeclared then how am I using it? In that case the compiler should be complaining about calls to malloc, just as it complains any other time I call a function that it hasn't seen a prototype for yet.
For that, '-pedantic' is required in addition to `-ansi'."
warning: ISO C does not allow extra `;' outside of a function
I'm just dumbfounded by that one. Not only does it require me to put a damned semicolon at the end of every line, but it also requires me to not put a semicolon in other places. I maintain my opinion that C is a little bitch.
When I first started learning this stupid required semicolon nonsense, I decided that the rules determining when a semicolon did and did not have to follow a closing bracket were to complex to bother learning considering how little time it takes to simply follow everything with a semicolon (assuming you remember to), and so instead I simply learned to follow everything with a semicolon.
Even if that option did guarantee that the C99 standard were strictly followed, that does not mean that every compiler out there supports C99 yet. Until there are more C99 compilers, using C99 features will limit your portability.
I can't say that bothers me. If people want to play with my source code, they can go get the compiler I'm using. If they don't want to do that, they can just use the binary.
Now if something that compiles with "-ansi" just fine on my Linux system doesn't compile on yours, then I think I definately want to go back to assembly language.
Why? Do you reject any language that changes?
No, not at all. I just don't like the idea of it being impossible to write a program that other people can compile without a problem.
My assembly programs will compile just fine on any Linux x86 system, because everything that the program uses is contained in the download. (Someone might have to download the latest version of NASM, but that's a lot easier than downloading the latest version of GCC.)
In C, half of my program (header files, libraries, etc.) is assumed to already be on the other person's computer. If any of it's missing or incorrect, then the program isn't going to compile correctly.
That's what I mean when I say that assembly is more portable than C. I can take an assembly program and recompile it on any other x86 linux system and it will compile and work without a problem, whereas if you take a C program that compiles on one person's x86 linux system, it may or may not compile on another's.
Like I said, 50% of what I download from sites like freshmeat.net won't compile correctly, despite the extreme probability that the person who wrote the code has an x86 linux system just as I do. Certainly it compiles just fine for the author, as they wouldn't bother to put something on the internet if it can't be compiled. They don't know that there is any problem, and even if they do, they're somewhat helpless to correct it as they don't have a system that exhibits the problem.
I don't want that to happen to me. I don't want to be the author that's spent all this time to write a program only to have it not work for 50% of the people who try to compile it because of some mysterious unknown reasons.
Assembly doesn't have that problem. If a program assembles and works on one x86 linux system, it will assemble and work on another x86 linux system just the same.
In the case of your code, the dereferencing could have been optimized away, since nothing was done with the dereferenced value.
That's why I used the volatile keyword.
Assuming you never call the C library or make any system calls.
Which isn't difficult to do. The only C function I've found so far that I would like to have in assembly is printf. Writing an assembly version shouldn't be difficult.
The FreeBSD version, on a much faster machine than the Linux version, went on for at least 5 minutes before I got bored waiting for it to stop. The Linux version took maybe 10 or 20 seconds to stop.
I'm really not sure why the linux version stops at all, it should get stuck in a loop just as the FreeBSD version does. I guess that the kernel detects the loop and kills the process, either that or it's a bug.
In the real world, with real programs, it is much safer not to have to reregister the handler, because a signal can come at any time, even between the automatic reset to SIG_DFL and the reregistering.
In that case, the signal handler has crashed, and another SIGSEGV isn't going to do any good.
SIGSEGV is not the only signal you might want to catch.
Yes, but when I get the SIGSEGV signal, only the handler for SIGSEGV is removed, any other handlers in place are preserved, even if they pointed to the same function. So having SIGSEGV automatically re-registeded doesn't do any good, since if the signal handler crashes, it'll just do it again if it gets called again. Usually. I actually have a program that takes a different execution path upon the second SIGSEGV, however even it uses the must-re-register variety of signal, since it chooses that path after calling signal(), and so if it crashes before then, then it'd just be stuck in a loop as well.
signal() is very old, and was originally the only way to go. The other functions came along later.
With the C library or with the kernel?
I notice that C's signal() doesn't call the kernel's signal(), but instead calls the kernel's sigaction() so that it can get the signal types which automatically re-register. The kernel's signal() doesn't provide that functionality.
No, C and it's undefined behavior are yucky. I don't understand how you can start with a system where variables are allocated on the stack and end up with a system where many of the functions aren't reentrant.
C is over 30 years old. On the PDP-11 you were limited to 64K text and 64K data. There were no threads. You could not write the massive multi-threaded programs people write today, and so you live with restrictions that today seem onerous.
Certainly we could drop the support for the 30 year old systems, maybe only support systems 20 years old?... That'd get us back to 1985, certainly no one's writing C programs that they expect to work on a TRS-80.
I would really like to use C, it's so much easier to just type "int x" than to do the equivelant in assembly language, but between these worthless library functions and code which one ANSI C compiler accepts but another ANSI C compiler rejects, C seems to be even less portable than assembly language.
That is just silly. Of course, you can write unportable code in C, but it is impossible to write portable assembly (portable to different machine architectures, that is). People have been writing robust, portable code in C for decades. It can be done.
So where do you go to learn all of the little details required to make your C programs compile on other systems with the same CPU, OS and compiler? I'd be happy if I could just do that with C, nevermind actual portability.
At least in assembly I can write a program and have it work on other people's x86 Linux systems, but if I try to do the same in C it won't work because their compiler will find a problem with the code that my compiler said was just fine, and vice versa.
Oh, really? Randy's HLA will not work on my Linux machine, because my version of gas does not recognize the .intel-syntax pseudo-op.
Like I said, downloading the latest NASM is much easier than downloading the latest GCC. NASM is just another program and easily replaceable, whereas GCC is pratically part of the OS.
I don't have nasm on that system at all.
pj@sucks:~/trash/nasm-0.98.39$ time ./configure real 0m8.745s user 0m3.110s sys 0m2.100s pj@sucks:~/trash/nasm-0.98.39$ time make real 0m39.173s user 0m27.240s sys 0m1.080s pj@sucks:~/trash/nasm-0.98.39$ time sudo make install real 0m0.321s user 0m0.010s sys 0m0.050s
Looks like you're only about 48 seconds away...
Again, much easier than upgrading GCC.
Of course, there's this minor issue:
gcc -c -g -O2 -Wall -std=c99 -pedantic -DHAVE_CONFIG_H -I. -I. -o nasm.o nasm.c
If you can't do c99, then it isn't going to work. And that shows what I'm talking about. Of the programs that I download every time I install a new distribution, the only ones I've come to expect to always compile are NASM and the le text editor. You're telling me that NASM won't compile on some of your systems. With actual knowledge that everything else sometimes does not compile, this leads me to suspect that le might be the only C program in existance that compiles correctly for everyone. That sucks.
I guess now I understand why things are the way they are. I can download assembly programs that other people have written for Linux and they assemble and work just fine, but when I download other people's C code, 95% of the time it won't compile without warnings, and 50% of the time it won't compile at all.
Portability does not happen by itself; you have to work at it. You have to learn, for instance, what language features are standard, and what are compiler-specific extensions. You have to stop assuming that ints and pointers are interchangeable. You have to learn not to rely on implementation-defined features.
However, there shouldn't be any portability issues when it comes to me downloading some code on the internet that was written on and for an x86 linux system, and compiling and using it on am x86 linux system. There's no porting going on there. We're both even using the same compiler. Yet it doesn't work.
I know most of them are using x86 Linux systems just like me, so I don't understand what the problem is, except that C seems to be the least portable language ever created.
Name one language that is more portable than C.
When C code can't even be taken from one system and compiled on another system with the same CPU, the same OS, and the same compiler, then it's not difficult to name a language that is more portable than C.
So here's some: Perl, java, and javascript all work on many different systems, with much smaller issues in portability than C has. (although I will admit that javascript is quite useless) As for same-system portability, we've got assembly language of course, then there's things like BASIC, and well, pretty much everything except for C. C is the only language I know of where I can take code written for a specific CPU, OS and compiler, and not get it to compile on a different system with the same CPU, OS and compiler it was written for.
I'm not talking about new features not existant in the old compiler here either. I download a new updated linux distribution about once a year, and I still can only get 50% of the programs I download to compile. There's just random issues with incompatability between header files and library functions and whatnot that makes portability a total bitch, and things like newer versions of the compiler creating errors on code that previous versions accepted without a problem is just another part of the issue. Things not compiling because they need a newer version of the compiler makes sense, but that's not what most of the problems with C are.
.
- References:
- Windows Assembly
- From: Richard Cooper
- Re: Windows Assembly
- From: JGCASEY
- Re: Windows Assembly
- From: Richard Cooper
- Re: Windows Assembly
- From: T.M. Sommers
- memmove crash
- From: Richard Cooper
- Re: memmove crash
- From: T.M. Sommers
- Re: memmove crash
- From: Richard Cooper
- Re: memmove crash
- From: T.M. Sommers
- Re: memmove crash
- From: Richard Cooper
- Re: memmove crash
- From: T.M. Sommers
- Windows Assembly
- Prev by Date: Re: Learning Windows and Assembler
- Next by Date: Re: Release of RosAsm V.2.025a
- Previous by thread: Re: memmove crash
- Next by thread: Re: Windows Assembly
- Index(es):
Relevant Pages
|