Operating System - HP-UX
1753278 Members
5749 Online
108792 Solutions
New Discussion юеВ

Re: NULL character assignment not working in C program

 
SOLVED
Go to solution
Curtis Deese
Frequent Advisor

NULL character assignment not working in C program

We are using the following version of cc on HP-UX 11.31 Itanium: cc: HP C/aC++ B3910B A.06.25 [Nov 30 2009]

I have the following function:

/*----------trim (char) c from right-side of string *p------------------*/
char *strtrim_right( char *p)
{
char *end;
int len;

len = strlen( p);
while ( *p && len)
{
WriteDebug("In strtrim_right 2 p='%s'", p);

end = p + len-1;
WriteDebug("In strtrim_right 2 end='%s'", end);

if(' ' == *end)
{
WriteDebug("In strtrim_right 3");
p[len-1] = '\0';
WriteDebug("In strtrim_right 4");
}
else
break;

len = strlen( p);
}
WriteDebug("In strtrim_right 5");

return( p);
}

Here is the output at the end of the log file:

25481-12:58:41.489-dbg In strtrim_right 2 p='Server Assigned. '
25481-12:58:41.489-dbg In strtrim_right 2 end=' '
25481-12:58:41.489-dbg In strtrim_right 3

Notice that it never gets to 'In strtrim_right 4'.

Why is my program terminating at the line p[len-1] = '\0'; ?

It also terminates the same way if I use p[len-1] = NULL;

How do I resolve the problem?
19 REPLIES 19
James R. Ferguson
Acclaimed Contributor

Re: NULL character assignment not working in C program

Hi:

When you inject a null byte into your string you are effectively terminating the string. Strings are arrays of characters that are terminated by a NULL byte.

The 'strlen()' function returns the number of characters in the string argument, not including the terminating null byte.

Regards!

...JRF...
Curtis Deese
Frequent Advisor

Re: NULL character assignment not working in C program

I know that a NULL character terminates a string and that a string is an array of characters. I am trying to terminate a string with a NULL character. Why does my program crash when I try to do that?
TwoProc
Honored Contributor

Re: NULL character assignment not working in C program

I always terminated my strings with "(char)0".

Main problem, you're not decrementing "len" inside of each loop, so you never rollback in the string enough to find the space character.

You're not decrementing len over each loop, which I'm a bit surprised at, since it's the driver for the while loop. Also, why fool with *end and with trying to move len around (and then somehow not doing it)?

Anyways, just for giggles, I wrote one, but haven't tested it - feel free to ignore.

char *strtrim_right(char *p)
{
int len = strlen(p);

while (len)
{
!(*(p+len)-(char)32)?
break:
len--;
}
len>0 ? *(p+len)=(char)0 : 0;
return (p);
}
We are the people our parents warned us about --Jimmy Buffett
Steven Schweda
Honored Contributor

Re: NULL character assignment not working in C program

> I know that a NULL character [...]

We normally refer to a NUL character and a
NULL pointer. But I digress.

> [...] Why does my program crash when I try
> to do that?

We non-psychics can't know why your program
crashes, because WE CAN'T SEE YOUR PROGRAM.
All we can see is an unbuildable fragment of
a program. If you want good free advice,
then you should make it easier for your
advisers to figure out what you're doing.

If I try to make what seems like a plausible
program out of your program fragment, then I
can _guess_ what your program may be doing.
In _my_ program, your function works once,
and fails once. Here's what my program does:

alp $ cc wd /list /show = (all, nomess)
alp $ link wd
alp $ run wd
Before (1): >Server Assigned. <
In strtrim_right 2 p='Server Assigned. '
In strtrim_right 2 end=' '
In strtrim_right 3
In strtrim_right 4
In strtrim_right 2 p='Server Assigned.'
In strtrim_right 2 end='.'
In strtrim_right 5
After (1): >Server Assigned.<
Before (2): >Server Assigned.<
In strtrim_right 2 p='Server Assigned. '
In strtrim_right 2 end=' '
In strtrim_right 3
%SYSTEM-F-ACCVIO, access violation, reason mask=04, virtual address=000000000001
01C8, PC=0000000000020158, PS=0000001B
%TRACE-F-TRACEBACK, symbolic stack dump follows
image module routine line rel PC abs PC
wd WD strtrim_right 2256 0000000000000158 0000000000020158
wd WD main 2276 00000000000002FC 00000000000202FC
wd WD __main 2270 0000000000000234 0000000000020234
0 FFFFFFFF8037FCE4 FFFFFFFF8037FCE4
%TRACE-I-END, end of TRACE stack dump

Line 2256 in the listing is the obvious one:

3 2256 p[len-1] = '\0';

alp $ help /mess /faci = system ACCVIO
[...]
The reason mask is
a longword whose lowest 5 bits, if set, indicate that the
instruction caused a length violation (bit 0), referenced the
process page table (bit 1), attempted a read/modify operation
(bit 2), was a vector operation on an improperly aligned
vector element (bit 3), or was a vector instruction reference
to an I/O space address (bit 4).
[...]

"reason mask=04" has bit 2 set, which means,
"attempted a read/modify operation".

My (actual, whole, real) program looks like
this:

alp $ type wd.c
#include
#include
#include

int WriteDebug( char *fmt, ...)
{
va_list ap;
int n;

va_start( ap, fmt);
n = vprintf( fmt, ap);
n += printf( "\n");
return n;
}


/*----------trim (char) c from right-side of string *p------------------*/
char *strtrim_right( char *p)
{
char *end;
int len;

len = strlen( p);
while ( *p && len)
{
WriteDebug("In strtrim_right 2 p='%s'", p);

end = p + len-1;
WriteDebug("In strtrim_right 2 end='%s'", end);

if(' ' == *end)
{
WriteDebug("In strtrim_right 3");
p[len-1] = '\0';
WriteDebug("In strtrim_right 4");
}
else
break;

len = strlen( p);
}
WriteDebug("In strtrim_right 5");

return( p);
}


int main ( void)
{

}
char str[] = "Server Assigned. ";

printf( "Before (1): >%s<\n", str);
strtrim_right( str);
printf( "After (1): >%s<\n", str);

printf( "Before (2): >%s<\n", str);
strtrim_right( "Server Assigned. ");
printf( "After (2): >%s<\n", str);
}

In my environment ...
alp $ cc /version
HP C V7.3-009 on OpenVMS Alpha V8.3
... I get a friendly error message with a
traceback. Yours is less convenient, but I
suspect that the problem there is the same as
the problem here. Did you get a "core" file?
Have you learned how to use a debugger with a
core file? It's a good skill to have on a
UNIX(-like) system.
Steven Schweda
Honored Contributor

Re: NULL character assignment not working in C program

> Main problem, [...]

Not really. (On many levels.)

> You're not decrementing len [...]

len = strlen( p);

(The second one.)

As usual, it's easier to explore an actual
program than it is a listing of a program
fragment. In fact, while probably not
ideally efficient, this thing does handle
multiple trailing spaces. For example:

alp $ run wd2
Before (1): >Server Assigned. <
In strtrim_right 2 p='Server Assigned. '
In strtrim_right 2 end=' '
In strtrim_right 3
In strtrim_right 4
In strtrim_right 2 p='Server Assigned. '
In strtrim_right 2 end=' '
In strtrim_right 3
In strtrim_right 4
In strtrim_right 2 p='Server Assigned. '
In strtrim_right 2 end=' '
In strtrim_right 3
In strtrim_right 4
In strtrim_right 2 p='Server Assigned.'
In strtrim_right 2 end='.'
In strtrim_right 5
After (1): >Server Assigned.<

What it can _not_ handle is a read-only
string argument.


> [...] (char)32

Not much on portable code are we? ASCII is
not the whole world. "' '" was better.

http://en.wikipedia.org/wiki/Extended_Binary_Coded_Decimal_Interchange_Code
Steven Schweda
Honored Contributor
Solution

Re: NULL character assignment not working in C program

Less stupid main program:

int main( void)
{
char str1[] = "Server Assigned. ";
char *str2 = "Server Assigned. ";

printf( "Before (1): >%s<\n", str1);
strtrim_right( str1);
printf( "After (1): >%s<\n", str1);

printf( "Before (2): >%s<\n", str2);
strtrim_right( str2);
printf( "After (2): >%s<\n", str2);
}


(Essentially the same results, just better
clarity and diagnostic messages.)


> [...] I wrote one, [...]

I don't really like code this compact --
too hard to add in those printf's -- but it's
an exercise.

char *strtrim_right( char *p)
{
int len;

for (len = strlen( p);
(len > 0) && (*(p+ (--len)) == ' ');
*(p+ len) = '\0');

return p;
}

Or, if you prefer subscripts to pointer
dereferencing:

for (len = strlen( p);
(len > 0) && (p[ --len] == ' ');
p[ len] = '\0');

As usual, many things are possible.


> [...] haven't tested it [...]

Testing, of course, is easier with a whole,
working program.
Dennis Handly
Acclaimed Contributor

Re: NULL character assignment not working in C program

>Steven: What it can _not_ handle is a read-only string argument.
char str1[] = "Server Assigned. ";
char *str2 = "Server Assigned. ";

Right. The first will work and the second abort (using the default options for +Olit=).
TwoProc
Honored Contributor

Re: NULL character assignment not working in C program

IMHO best one is Steven's below as the cleanest:

for (len = strlen( p);
(len > 0) && (p[ --len] == ' ');
p[ len] = '\0');
We are the people our parents warned us about --Jimmy Buffett
Steven Schweda
Honored Contributor

Re: NULL character assignment not working in C program

> IMHO best one is [...]

"best" is not well-defined here. Note that
that "for" loop stores a NUL over every
trailing space character, not only the
left-most one, so, while the code may be
compact, it may run more slowly than smarter
code which stores only the one required NUL
(in the right place). And, the speed of any
such code may depend on the input data --
more or fewer trailing spaces. Everything's
complicated.