From: Lothar Behrens on
Hi,

I tried a simple test application and I fail to catch the exception in
my catch block. Why does this not work?

I am using Mac OS X 10.5.x, but I think as this is a plain UNIX issue
it will behave identical on Linux.

The code (test.cpp):

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define THROWN_SIG( why ) \
printf("%s%s%s", "Exception catched by MiniCppUnit: \n",
"what() : ", #why);

#define THROWN( why ) \
printf("%s%s%s", "Exception catched by MiniCppUnit: \n",
"what() : ", #why); \
throw ;

#define TERM( why ) \
printf("%s%s%s", "Exception catched by MiniCppUnit: \n",
"what() : ", #why); \
exit(1);


void sig_handler(int signr) {
switch (signr) {
case SIGBUS:
THROWN("SIGBUS happened.");
break;
default:
break;
}
}

int main() {
signal(SIGBUS, sig_handler);

try {
int len = strlen(NULL);
} catch (...) {
printf("Really catched\n");
}

}

g++ -g test.cpp -o test
From: Moi on
On Sat, 03 Apr 2010 10:30:41 -0700, Lothar Behrens wrote:

> Hi,
>
> I tried a simple test application and I fail to catch the exception in
> my catch block. Why does this not work?
>
> I am using Mac OS X 10.5.x, but I think as this is a plain UNIX issue it
> will behave identical on Linux.
>
> The code (test.cpp):
>
> #include <signal.h>
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
>
> #define THROWN_SIG( why ) \
> printf("%s%s%s", "Exception catched by MiniCppUnit: \n",
> "what() : ", #why);

You cannot call printf from a signal handler.
(it is not "signal-safe" )

> int main() {
> signal(SIGBUS, sig_handler);

a NULL pointer dereference generates a SEGV.
SIGBUS is mostly used for alignment-errors.

> try {
> int len = strlen(NULL);
> } catch (...) {
> printf("Really catched\n");

Nitpick: "Caught"

Try:

******************************/

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>

sigjmp_buf the_jump;

int my_strlen(char *str);
void sig_handler(int signr);

void sig_handler(int signr) {
switch (signr) {
case SIGBUS:
siglongjmp(the_jump,1);
break;
case SIGSEGV:
siglongjmp(the_jump,2);
break;
default:
break;
}
}

int my_strlen(char *str)
{
switch (sigsetjmp(the_jump, -1)) {
case 0:
return strlen (str);
case 1:
return -1;
case 2:
return -2;
default:
return -3;
}
}

int main()
{
int rc;

signal(SIGBUS, sig_handler);
signal(SIGSEGV, sig_handler);

rc = my_strlen(NULL);
printf("my_strlen(NULL) =%d\n", rc);

return 0;
}


/*****************
[ which is of course silly; it would be much easier for my_strlen()
to check, e.g. if (!str) return -2;
]
HTH,
AvK
From: Lothar Behrens on
On 3 Apr., 19:59, Moi <r...(a)invalid.address.org> wrote:
> On Sat, 03 Apr 2010 10:30:41 -0700, Lothar Behrens wrote:
> > Hi,
>
> > I tried a simple test application and I fail to catch the exception in
> > my catch block. Why does this not work?
>
> > I am using Mac OS X 10.5.x, but I think as this is a plain UNIX issue it
> > will behave identical on Linux.
>
> > The code (test.cpp):
>
> > #include <signal.h>
> > #include <stdio.h>
> > #include <string.h>
> > #include <stdlib.h>
>
> > #define THROWN_SIG( why ) \
> >         printf("%s%s%s", "Exception catched by MiniCppUnit: \n",
> > "what() : ", #why);
>
> You cannot call printf from a signal handler.
> (it is not "signal-safe" )
>
> > int main() {
> >         signal(SIGBUS, sig_handler);
>
> a NULL pointer dereference generates a SEGV.
> SIGBUS is mostly used for alignment-errors.
>
> >         try {
> >                 int len = strlen(NULL);
> >         } catch (...) {
> >                 printf("Really catched\n");
>
> Nitpick: "Caught"
>
> Try:
>
> ******************************/
>
> #include <signal.h>
> #include <stdio.h>
> #include <string.h>
> #include <stdlib.h>
> #include <setjmp.h>
>
> sigjmp_buf the_jump;
>
> int my_strlen(char *str);
> void sig_handler(int signr);
>
> void sig_handler(int signr) {
>         switch (signr) {
>         case SIGBUS:
>               siglongjmp(the_jump,1);
>               break;
>         case SIGSEGV:
>               siglongjmp(the_jump,2);
>               break;
>         default:
>               break;
>         }
>
> }
>
> int my_strlen(char *str)
> {
> switch (sigsetjmp(the_jump, -1)) {
> case 0:
>         return strlen (str);
> case 1:
>         return -1;
> case 2:
>         return -2;
> default:
>         return -3;
>         }
>
> }
>
> int main()
> {
> int rc;
>
> signal(SIGBUS, sig_handler);
> signal(SIGSEGV, sig_handler);
>
> rc = my_strlen(NULL);
> printf("my_strlen(NULL) =%d\n", rc);
>
> return 0;
>
> }
>
> /*****************
> [ which is of course silly; it would be much easier for my_strlen()
> to check, e.g. if (!str) return -2;
> ]
> HTH,
> AvK

I understand the implementation. I don't understand, why such
functions doesn't check against NULL pointer by itself.

I also thought about my own strlen function, but I liked to avoid
wrapping all these functions.
I think, as I'll setup my unit tests, I should simply exit(1) in such
a case and only report where the failure of the unit test came from.

If I would do my_strlen, I'll surely have to wrap more than strlen :-)

Thanks

Lothar
From: Moi on
On Sat, 03 Apr 2010 11:28:02 -0700, Lothar Behrens wrote:

> On 3 Apr., 19:59, Moi <r...(a)invalid.address.org> wrote:
>> On Sat, 03 Apr 2010 10:30:41 -0700, Lothar Behrens wrote:

>
> I understand the implementation. I don't understand, why such functions
> doesn't check against NULL pointer by itself.
>
> I also thought about my own strlen function, but I liked to avoid
> wrapping all these functions.
> I think, as I'll setup my unit tests, I should simply exit(1) in such a
> case and only report where the failure of the unit test came from.
>
> If I would do my_strlen, I'll surely have to wrap more than strlen :-)
>

It is all a question of semantics.
In some cases it is convenient to distinguish between
"there is no string" and "there is an empty string".

In the case of "there is no string" (NULL pointer) there
is no reason to call strlen (or any of the other string functions)
The caller should know this, so there is no reason for the function
to check this (again).

The same goes for:
fprintf(NULL, "%s\n", "this is a string" );

and _maybe_ for
fprintf(stderr, "%s\n", NULL);


The caller knows := the caller should decide.

HTH,
AvK
From: Scott Lurndal on
Moi <root(a)invalid.address.org> writes:
>On Sat, 03 Apr 2010 11:28:02 -0700, Lothar Behrens wrote:
>
>> On 3 Apr., 19:59, Moi <r...(a)invalid.address.org> wrote:
>>> On Sat, 03 Apr 2010 10:30:41 -0700, Lothar Behrens wrote:
>
>>
>> I understand the implementation. I don't understand, why such functions
>> doesn't check against NULL pointer by itself.
>>
>> I also thought about my own strlen function, but I liked to avoid
>> wrapping all these functions.
>> I think, as I'll setup my unit tests, I should simply exit(1) in such a
>> case and only report where the failure of the unit test came from.
>>
>> If I would do my_strlen, I'll surely have to wrap more than strlen :-)
>>
>
>It is all a question of semantics.
>In some cases it is convenient to distinguish between
>"there is no string" and "there is an empty string".
>
>In the case of "there is no string" (NULL pointer) there
>is no reason to call strlen (or any of the other string functions)
>The caller should know this, so there is no reason for the function
>to check this (again).
>
>The same goes for:
>fprintf(NULL, "%s\n", "this is a string" );
>
>and _maybe_ for
>fprintf(stderr, "%s\n", NULL);
>
>
>The caller knows := the caller should decide.

True. That said, BSD used to map a read-only page of zeros into the
process address space at address zero, thus strlen(NULL) would return
0 instead of a signal. This led to some pretty sloppy programming,
some of which still bites every now and again.

scott