Re: memmove crash
- From: "T.M. Sommers" <tms@xxxxxx>
- Date: Mon, 19 Sep 2005 15:58:13 GMT
Richard Cooper wrote:
On Fri, 16 Sep 2005 00:49:32 -0400, T.M. Sommers <tms@xxxxxx> wrote:
Why not reduce the code to the bare minimum necessary to show the problem, and post it?
That was the first thing I tried to do, but my test program didn't reproduce the problem.
Which usually means that the problem is in the code that was removed.
Anyway, a simple strace reveals the part of the problem:
--- SIGSEGV (Segmentation fault) @ 0 (0) --- --- SIGSEGV (Segmentation fault) @ 0 (0) --- +++ killed by SIGSEGV +++
Two consecuative segmentation faults without a re-registration of the signal handler.
Which is what I suggested. Some Linux kernels and libcs follow the old signal behavior, in which the handler is reset to SIG_DLF when a signal is caught; other versions follow the BSD model, and don't. So the first step is to determine which behavior your system follows.
Here's the code:
#include <asm/unistd.h> #include <stdio.h> #include <string.h>
void handler(int);
int main(void) {
/* Register a signal handler directly with the kernel. */ int result; asm volatile ( "int $0x80" :"=a" (result) :"a" (__NR_signal), "b" (11), "c" (handler) ); printf("Result of kernel call: %d\n", result);
signal() does not return an int; it returns a sighandler_t in Linux.
/* Allocate some memory... */ char *memory1; memory1 = (char*) malloc(4096); char *memory2; memory2 = (char*) malloc(4096);
Don't cast the value returned by malloc(), and be sure to include stdlib.h. And, of course, you should test the return value from malloc().
If you care about portability, you should probably not use the C99 feature that allows intermixing of data definitions and code, as that is not yet implemented everywhere. This would not compile on my (old) Linux system.
printf("Malloc's pointer: %u\n", memory1);
printf("Malloc's pointer: %u\n", memory2);
Better to use %p to print a pointer value.
/* Do a perfectly safe memmove(). */ memmove(memory1, memory2, 4096);
/* Cause a segmentation fault. */ volatile int *crash = NULL; *crash++;
Why not use raise()?
/* Cause a different segmentation fault. */ memmove(memory2, memory1, -4096);
This, I think, is the real problem. My understanding is that this invokes undefined behavior. I see nothing in the C or POSIX standards that requires a SIGSEGV to be raised in the case of undefined behavior. The system can do anything at all. FreeBSD seems to get into an infinite loop, or at least a loop that goes on beyond my patience. Solaris does raise a signal.
/* Keep GCC from complaining... */ return 0;
You put in a return not to keep gcc happy, but because main is supposed to return an int, so you should return one.
};
void handler(int signum) { printf("Recieved Signal #%d\n", signum);
This is a potential problem. It is not safe to call printf() in a signal handler. write() is okay, though.
_exit(1); };
But the solution to your problem is easy: use atexit().
-- Thomas M. Sommers -- tms@xxxxxx -- AB2SB
.
- Follow-Ups:
- Re: memmove crash
- From: Richard Cooper
- Re: memmove crash
- 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
- Windows Assembly
- Prev by Date: Re: Release of RosAsm V.2.025a
- Next by Date: Re: Maybe we should stop "Paging Beth Stone" already...
- Previous by thread: memmove crash
- Next by thread: Re: memmove crash
- Index(es):
Relevant Pages
|