doubt on char *

F

Fastro

int myfun(char *sourcebuf)
{
char *destbuf;
char ch;
while (*sourcebuf != '\0')
{
*destbuf++=*sourcebuf++; --> crashed here
};
return 1;
}

Can any one explain why it is crashed?
Thankyou...
 
K

Kenny McCormack

int myfun(char *sourcebuf)
{
char *destbuf;
char ch;
while (*sourcebuf != '\0')
{
*destbuf++=*sourcebuf++; --> crashed here
};
return 1;
}

Can any one explain why it is crashed?
Thankyou...

It may be a bug in your editing software.

When you wrote:

int myfun(char *sourcebuf, char *destbuf)

It came out as:

int myfun(char *sourcebuf)
{
char *destbuf;

And, unfortunately, the compiler couldn't fix this by itself.
 
R

rahul

It may be a bug in your editing software.

When you wrote:

int myfun(char *sourcebuf, char *destbuf)

It came out as:

int myfun(char *sourcebuf)
{
char *destbuf;

And, unfortunately, the compiler couldn't fix this by itself.

Its either this or Fastro really forgot to assign memory to destbuf
and dereferenced god knows what.
 
R

rams

Its either this or Fastro really forgot to assign memory to destbuf
and dereferenced god knows what.

yes ,allocate memory for destbuf using malloc() &strlen()
like destbuf=(char *)malloc(1+ strlen(sourcebuf)*sizeof(char) );
and finally after coming out of while loop make sure to NULL the last
character of destbuf
i.e .., *destbuf='\0';
and at last don't forget to free the memory
 
S

santosh

rahul said:
Its either this or Fastro really forgot to assign memory to destbuf
and dereferenced god knows what.

Er, Kenny was being his usual sarcastic self. It's extremely unlikely to
be a bug in the editor. It's more likely a bug in the OP. :)
 
C

Chris Dollin

rams said:
yes ,allocate memory for destbuf using malloc() &strlen()
like destbuf=(char *)malloc(1+ strlen(sourcebuf)*sizeof(char) );

(a) there's no need to, and good reasons for not, cast the `malloc`
result to `char*`.

(b) `sizeof char` is 1 by definition.

char *destbuf = malloc( 1 + strlen( sourcebuf ) );

is, I think, clearer and safer. (I'd write `+ 1` rather than `1 +`,
but I can see the point of marking the one-more-than in this way.)
 
J

Joachim Schmitz

CBFalconer said:
Fastro wrote: ** code edited slightly **

Yes. destbuf is uninitialized. It doesn't point to any storage.
A step further: because it is uninitialized, it'll contain some garbage
value, that, if interpreted as a pointer, will try to access some random
memory location. If you're lucky, you don't own that and the OS will carsh
the program, if you're unlucky, you'll own it and accessing it will corrupt
some data structuturs and you'll only notice the harm it did much later and
have major difficulties to find were it went wrong.
So be hapy it crashed on you right away...

Bye, Jojo
 
R

Richard

Joachim Schmitz said:
A step further: because it is uninitialized, it'll contain some garbage
value, that, if interpreted as a pointer, will try to access some random
memory location. If you're lucky, you don't own that and the OS will carsh
the program, if you're unlucky, you'll own it and accessing it will corrupt
some data structuturs and you'll only notice the harm it did much later and
have major difficulties to find were it went wrong.
So be hapy it crashed on you right away...

Bye, Jojo

Look up using something like splint. Also consider using a
debugger. Both will make it very clear where the error is.

http://www.splint.org/

I use this all the time and have bound it to me emacs IDE so any emacs
users out there, here you are:


,----
| (defun do-lint()
| (interactive)
| (set (make-local-variable 'compile-command)
| (let ((file (file-name-nondirectory buffer-file-name)))
| (format "%s %s %s"
| "splint"
| "+single-include -strict -compdef -nullpass -preproc +matchanyintegral -internalglobs -I/usr/include/gtk-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/cairo/ -I/usr/include/pangomm-1.4/pangomm/"
| file
| )))
| (message compile-command)
| (compile compile-command)
| )
`----
 
S

santosh

Joachim said:
A step further: because it is uninitialized, it'll contain some
garbage value, that, if interpreted as a pointer, will try to access
some random memory location. If you're lucky, you don't own that and
the OS will carsh the program, if you're unlucky, you'll own it and
accessing it will corrupt some data structuturs and you'll only notice
the harm it did much later and have major difficulties to find were it
went wrong. So be hapy it crashed on you right away...

To the OP:

This is one reason for those who advocate initialising all pointer
objects with their proper values or NULL. Null pointer de-referencing
is guaranteed to be caught, instead of causing damage behind your back.
 
R

Richard

santosh said:
To the OP:

This is one reason for those who advocate initialising all pointer
objects with their proper values or NULL. Null pointer de-referencing
is guaranteed to be caught, instead of causing damage behind your
back.

As a "failsafe" addition I would agree - especially with the
initializing with their proper values. C99 type code no doubt, but there
you go:

e.g

char * szBuffer = malloc(SIZENEEDED);

I would still strongly suggest something like splint or similar if you
are learning. These tools can be anal to the extreme but boy do you
learn quickly! if you are not keen to keep strandards compliant with old
dusty ones then use C99 for variable declarations and keep those temps
as local as possible to the lines which use them too.
 
S

santosh

Richard said:
As a "failsafe" addition I would agree - especially with the
initializing with their proper values. C99 type code no doubt, but
there you go:

e.g

char * szBuffer = malloc(SIZENEEDED);

Are you talking about mixed code and declarations? If so, yes, that's
another way to restrict objects to the minimum necessary scope, and you
would not need dummy initialisations.
I would still strongly suggest something like splint or similar if you
are learning. These tools can be anal to the extreme but boy do you
learn quickly! if you are not keen to keep strandards compliant with
old dusty ones then use C99 for variable declarations and keep those
temps as local as possible to the lines which use them too.

And if a pointer's scope is larger than strictly necessary, a good idea
is to set it to NULL immediately after you've finished with it. If it's
not inadvertently used later on, an optimising compiler is likely to
optimise away the assignment to NULL.
 
B

Barry Schwarz

To the OP:

This is one reason for those who advocate initialising all pointer
objects with their proper values or NULL. Null pointer de-referencing
is guaranteed to be caught, instead of causing damage behind your back.

Dereferencing a NULL pointer invokes undefined behavior. Evaluating
an indeterminate value (such as dereferencing an uninitialized
pointer) invokes undefined behavior. The standard guarantees nothing
more for either. It is the system (hardware and OS) and probably the
implementation (compiler and run-time library) that determine if
either of these two examples of undefined behavior are "caught".


Remove del for email
 
J

Joachim Schmitz

Barry said:
Dereferencing a NULL pointer invokes undefined behavior. Evaluating
an indeterminate value (such as dereferencing an uninitialized
pointer) invokes undefined behavior. The standard guarantees nothing
more for either. It is the system (hardware and OS) and probably the
implementation (compiler and run-time library) that determine if
either of these two examples of undefined behavior are "caught".
Mind to name implementations that do not catch this? Other than DS9K?

Bye, Jojo
 
W

Walter Roberson

Barry Schwarz wrote:
Mind to name implementations that do not catch this? Other than DS9K?

SGI IRIX64 does not catch dereferencing a NULL pointer.

SGI IRIX was designed with an unwritable 4Kb page starting from
address 0, which was then followed in the process address space
by code for the graphics library, with the graphics library code having
been tightly tuned to take advantage of the fact that on that
architecture (MIPS) low virtual addresses could be represented in
shorter instructions (less memory, better use of cache.)

When SGI created its 64 bit operating system, IRIX64 (which included
a substantial amount of backwards compatability, including the
ability to run the prior "32 bit" binaries), it increased its kernel
page size from 4 Kb to 8 Kb. So suddenly the memory page that covered
the 4 Kb to 8 Kb range was a part of the memory page starting from address 0
rather than being a distinct page. In order to provide the accesses
needed for the graphics library, SGI had to unprotect the memory
from virtual address 0 to 8 Kb (minus 1).

In my experience, in this setup, direct writes to address 0 (that
is, direct dereferences of the NULL pointer) were not as common
as writes to addresses with small offsets -- addresses arising
out of code of the form structureptr->field where structureptr
happened to be NULL.


Dereferencing an uninitialized pointer is problematic on many architectures;
if the pointer is an auto variable on a stack, the pointer value could
turn out to be whatever happened to have been in that memory last.
On the processors I have happened to examine, the standard "allocate
a chunk of memory for a stack frame" sequence seldom automatically
zeroed the memory (though the compiler might choose to add instructions
that set it to some particular value.)
 
S

santosh

Eric said:
See Walter Roberson's post for an illustration of the
strength of the "guarantee" ...

Yes, sorry to the OP. This is what comes of programming for too long on
modern memory protected operating systems.
As for the practice of "I've got nothing better to do at
the spot where this pointer variable is declared, so I'll
initialize it to NULL for safety's sake," you're right that
some people advocate it. IM not so HO they make a poor trade
by doing so: They gain a (probable) run-time crash at the
expense of a (probable) compile-time or lint-time diagnostic.

char *p /* = NULL */ , *q /* = NULL */ ;
if (something) {
if (something_else) {
p = "Hello";
if (random_circumstance)
q = "world";
if (other_random_circumstance)
q = "Chicago";
}
else {
q = "my ragtime gal";
if (whatever)
p = "Hello";
else
p = "Good-bye";
}
}
else ... /* and so on in that vein */

printf ("%s %s\n", p, q);

If the NULL initializations are included you may get a run-time
error at the printf(), if your test cases happen to hit the
right combination of circumstances. If the initializations are
omitted, many compilers and lints will issue a diagnostic about
the use of potentially garbage values, which they almost certainly
will not do if the initializations are present.

The cost of an error usually increases with the amount of time
it remains undetected in the code, so it seems to me that a policy
of giving up an inexpensive error-catch in favor of an expensive
one is misguided.

Yes. That advice is also useful only for those systems that do trap null
pointer access. I would've qualified my statements had I been thinking
clearly.

Now that we are having this discussion anyway, do you know of any
compilers that diagnose attempts to use a null pointer, particularly
when the execution environment would allow it? Purely based on
information from the source code of course. It would just be a step
more involved than the diagnostics for using uninitialised objects.
 
J

Joachim Schmitz

pete said:
I do mind, but I'll do it anyway.


new.c freezes on Windows XP, MSVC++ V5.0

C:\Program Files\DevStudio\SharedIDE\bin\Debug>new
/* BEGIN new.c output */
^C
C:\Program Files\DevStudio\SharedIDE\bin\Debug>




/* BEGIN new.c */

#include <stdio.h>

int main(void)
{
char *a = NULL;

puts("/* BEGIN new.c output */");
if (*a == 0) {
puts("wow");
}
puts("/* END new.c output */");
return 0;
}

/* END new.c */
Not for me (Same Platform, same Compiler, but the Express version), here it
crashes just like expected.

Bye, Jojo
 
C

CD1

(a) there's no need to, and good reasons for not, cast the `malloc`
    result to `char*`.

(b) `sizeof char` is 1 by definition.

    char *destbuf = malloc( 1 + strlen( sourcebuf ) );

is, I think, clearer and safer. (I'd write `+ 1` rather than `1 +`,
but I can see the point of marking the one-more-than in this way.)

--
"Shopping."                                                          /Barrayar/

Hewlett-Packard Limited                                          registered no:
registered office: Cain Road, Bracknell, Berks RG12 1HN          690597 England

Well, I think the statement:

char *destbuf = (char *) malloc(1 + strlen(sourcebuf) * sizeof(char));

is clearer and safer than yours, for the following reasons:

(a) If destbuf is of type char *, it makes the code clearer to cast
the return of malloc to that type, even if it's unnecessary. And if
I'm not mistaken, in C++ you must cast void * to char * explicitly, so
in case this code has to be compiled in a C++ environment, no changes
would be necessary.
(b) If you use sizeof to calculate the size of the other primitive
types, pointers and structs, why not use it also to calculate the size
of a char? I didn't know sizeof(char) is 1 by definition, but it's an
"exception" in your coding rules: "use sizeof to calculate the size of
every type, but char".

Just my opinion :)
 
C

Chris Dollin

CD1 said:
Well, I think the statement:

char *destbuf = (char *) malloc(1 + strlen(sourcebuf) * sizeof(char));

is clearer and safer than yours, for the following reasons:

(a) If destbuf is of type char *, it makes the code clearer to cast
the return of malloc to that type, even if it's unnecessary.

I disagree that it's clearer, and it's less safe (less so nowadays);
in the absence of a proper declaration for `malloc`, the compiler is
/required/ to produce a diagnostic for the conversion from (implicit)
int to pointer, but /not/ required to do so given the cast.
And if
I'm not mistaken, in C++ you must cast void * to char * explicitly,

I don't care. C code is for C compilers.
so in case this code has to be compiled in a C++ environment,

.... you would compile it with a C compiler.
no changes would be necessary.

Quite true; C compilers work even in the presence of C++ compilers.
(b) If you use sizeof to calculate the size of the other primitive
types, pointers and structs, why not use it also to calculate the size
of a char?

Because it introduces unnecessary clutter and incorrectly suggests
that the code generalises to different types. It doesn't; if we're
not workinf with `char`, then the `strlen` stuff is broken anyway.
I didn't know sizeof(char) is 1 by definition, but it's an
"exception" in your coding rules: "use sizeof to calculate the size of
every type, but char".

Even if that were my rule, that's not an exception; that would
/be/ the rule. But that's not the rule [1]. In this case, it
would be more like "if the code only works with chars, then
it's unnecessary complication to use `sizeof(char)`".

In the case where the type may reasonably change, then I'd use
the well-known idiom:

Type *it = malloc( someExpressionNotJust_1 * sizeof (*it) );
Just my opinion :)

Not mine alone ...

[1] "More a sort of guideline."
 
F

Fastro

I use two distinct formats and one related format,
for most malloc calls:

#include <stdlib.h>

a = malloc(string_length + 1);
b = malloc(N * sizeof *b);
c = malloc(sizeof *c);

Thanks all...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top