handling uninitialized pointed (How to check ?? )

S

sanjaymeher

Hi,

Right now addDynamicMemory(char **ptr, int size) method can able to
handle if input ptr is intitialized to NULL or something. But how to
improve this method to handle uninitialized pointed even. Any Answer ??

Thanks,
Sanjay


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

int addDynamicMemory(char **ptr, int size)
{
/* See and chek whether size memory is available or not */
int currSize;
if(*ptr == NULL)
{
*ptr = (char*) malloc(size * sizeof(char));
if(ptr == NULL)
{
printf("Initialized memory as null \n");
return -1;
}
else
{
printf("Can not Initialized memory as null \n");
return -1;
}
}

currSize = strlen(*ptr);
size = currSize + size;
*ptr = (char*) realloc(*ptr, size*sizeof(char));

if(ptr != NULL)
{
printf(" re Allocation size is %d\n",size);
return 0;
}

printf(" re Allocation failed \n");
return -1;
}

//int main(int argc, char* argv[])
void main()
{
char *test;
test = NULL;

addDynamicMemory(&test, 40);
printf("At first test value is %s\n",test);
strcpy(test,"444444444");
printf("After allocation val is %s\n", test);

addDynamicMemory(&test, 50);
strcat(test,"5555555555");
printf("After allocation val is %s\n", test);
}
 
R

Richard Heathfield

(e-mail address removed) said:
Hi,

Right now addDynamicMemory(char **ptr, int size) method can able to
handle if input ptr is intitialized to NULL or something. But how to
improve this method to handle uninitialized pointed even. Any Answer ??

Don't send it uninitialised pointers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int addDynamicMemory(char **ptr, int size)

int addDynamicMemory(char **ptr, size_t size)
{
/* See and chek whether size memory is available or not */
int currSize;

size_t currSize;
char *tmp; /* you'll need this in a minute */
if(*ptr == NULL)

If ptr is NULL, *ptr is a bad move.
{
*ptr = (char*) malloc(size * sizeof(char));

*ptr = malloc(size);
if(ptr == NULL)

Too late.
{
printf("Initialized memory as null \n");
return -1;
}
else
{
printf("Can not Initialized memory as null \n");
return -1;
}
}

currSize = strlen(*ptr);
size = currSize + size;
*ptr = (char*) realloc(*ptr, size*sizeof(char));

currSize = strlen(*ptr);
tmp = realloc(*ptr, size);
if(tmp != NULL)
{
*ptr = tmp;
size += currSize;
}
else
{
You have some work to do. The call failed. How will you handle this?
}
if(ptr != NULL)
{
printf(" re Allocation size is %d\n",size);

Because the right type for size is size_t, %d won't cut it any more.
return 0;
}

printf(" re Allocation failed \n");
return -1;
}

//int main(int argc, char* argv[])
void main()

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

char *test = NULL;
addDynamicMemory(&test, 40);

Why bother returning a value if you don't test it?
 
M

Madhav

Hi,

Right now addDynamicMemory(char **ptr, int size) method can able to
handle if input ptr is intitialized to NULL or something. But how to
improve this method to handle uninitialized pointed even. Any Answer ??
Do you mean to check for pointers containing random values other than
NULL? I think you are talking about a case when you just pass a pointer
to your addDynamicMemory( ) which is not "malloc()ed" and which is not
null.

I think you cannot test this case. Either you have to make it NULL
explicitly before passing it to your own addDynamicMemory() or allocate
some space for it.

Please correct me if I am wrong.

-Madhav.
 
S

sanjaymeher

I just want to call like this


void main()
{
char *test;
//test = NULL; (Dont want to initialize it here ......)

addDynamicMemory(&test, 40);

}
 
R

Richard Heathfield

(e-mail address removed) said:
I just want to call like this


void main()

main returns int. I told you that already, I'm sure. If you can't get that
right, you are not ready for malloc.
 
S

slebetman

I just want to call like this

void main()

int main()
{
char *test;
//test = NULL; (Dont want to initialize it here ......)

Simple:

char *test = NULL;

If you ALWAYS declare pointers like this, you will have no problems.
The answer is simply to NEVER declare pointer without initialising it
to NULL. If you see anywhere in your code where you declare a pointer
that is not initialised to NULL consider is a BUG. It's only 8
characters including spacebars, why not just type it?

Again: ALWAYS declare pointers by initialising it to NULL:

char *test = NULL;
int *idx = NULL;
char *buffer = NULL;
...
 
M

Madhav

I just want to call like this


void main()
{
char *test;
//test = NULL; (Dont want to initialize it here ......)

addDynamicMemory(&test, 40);

}

The problem in this case is that you dont know (and can't check)
whether the "test" pointer points to a valid address in the heap. In
the code above, it could point to anything because the standard does
not specify initial value for pointers.

Also, please change the return type of main to int, and add a
"void" within the brackets if you don't want to use the command line
arguments.
 
K

Kenny McCormack

Hi,

Right now addDynamicMemory(char **ptr, int size) method can able to
handle if input ptr is intitialized to NULL or something. But how to
improve this method to handle uninitialized pointed even. Any Answer ??

I don't know. Speak English, maybe?
 
S

sanjaymeher

I wanted this method to be full proof to be used by other user. My
method should able to handle if any uninitialized variable is coming..
This is really not the good part of C language if i try to speak
ENGLISH ....

Thanks
Sanjay
 
R

Richard Heathfield

(e-mail address removed) said:
I wanted this method to be full proof to be used by other user. My
method should able to handle if any uninitialized variable is coming..

You simply can't do it, at least not without writing your own implementation
and then requiring all your users to use it. This solution might just be
considered beyond the scope of the discussion.
 
P

pemo

Richard Heathfield said:
(e-mail address removed) said:


You simply can't do it, at least not without writing your own
implementation
and then requiring all your users to use it. This solution might just be
considered beyond the scope of the discussion.

As you've been told, you can't do this in C.

You perhaps ought to look at C++ - where one can use a smart-pointer that
'knows' whether it's been assigned to and/or explicitly initialised.

A rather old book that goes into this kind of thing at length is called 'C++
Pointers and Dynamic Memory Management' [yes, it's a whole book on these
prickly subjects]. Probably out of print now; though you can find plenty of
web sources on this subject.
 
C

Chad

Richard said:
(e-mail address removed) said:


Don't send it uninitialised pointers.


int addDynamicMemory(char **ptr, size_t size)


size_t currSize;
char *tmp; /* you'll need this in a minute */


If ptr is NULL, *ptr is a bad move.

Maybe I didn't think about this enough, but how can *ptr be a bad move.
When i go something like:

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

int addmem(char **ptr, size_t size) {

if(*ptr == NULL) {
printf("Nada \n");
exit(1);
}
return 0;
}

int main(void) {
char *test = NULL;
addmem(&test, 40);

return 0;
}

I get the following:
gcc -Wall dyn.c -o dyn
./dyn Nada

However, when I change the expression to
if(ptr == NULL)
my computer outputs nothing.

Chad
 
C

Chad

Chad said:
Maybe I didn't think about this enough, but how can *ptr be a bad move.
When i go something like:

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

int addmem(char **ptr, size_t size) {

if(*ptr == NULL) {
printf("Nada \n");
exit(1);
}
return 0;
}

int main(void) {
char *test = NULL;
addmem(&test, 40);

return 0;
}

I get the following:

However, when I change the expression to
if(ptr == NULL)
my computer outputs nothing.

Chad

I just noticed that I cut and pasted the sample code, I forgot to
include
#include<stdio.h>
 
A

Anand

Chad said:
Richard Heathfield wrote: [...]
int addDynamicMemory(char **ptr, int size) [...]
if(*ptr == NULL)

If ptr is NULL, *ptr is a bad move.


Maybe I didn't think about this enough, but how can *ptr be a bad move.
When i go something like:

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

int addmem(char **ptr, size_t size) {

if(*ptr == NULL) {
printf("Nada \n");
exit(1);
}
return 0;
}

int main(void) {
char *test = NULL;
addmem(&test, 40);

return 0;
}

I get the following:
gcc -Wall dyn.c -o dyn
./dyn

Nada


However, when I change the expression to
if(ptr == NULL)
my computer outputs nothing.

Chad
There are two levels of check that is required here.

What happens if I call: addmem(NULL, 40);

So, it's upto you to decide what level of protection you are giving
about bad/wrong usage of your code.

I think, what Richard Heathfield was suggesting was to provide this one
extra level of blanket to ensure that ptr itself to be non-NULL before
redirecting it.

In general, IMHO, it's always a good idea to ensure the ptr is non-NULL
before its redirection (at least its first redirection in your
module/function.)

So an assert( ptr != NULL );
or
if (ptr != NULL)
{
printf("WTH?\n");// or WTF if you prefer
....
}
and then followed by the *ptr != NULL test is bit more idiot-proof.
 
C

Chris Torek

I wanted this
Code:
 to be [fool]proof ... [and thus catch[/QUOTE]
 uninitialized variables]

There is really nothing special about pointers in this regard.
Consider a simple function int f(int x) that returns (x + 1) mod 5,
i.e., counts 0, 1, 2, 3, 4, 0, 1, ....  We can write this as:

    int f(int x) {
        ++x;
        if (x >= 5)
            x -= 5;
        return x;
    }

But if you call f() with an uninitialized variable, you may get
an out-of-range result: f(1234) produces 1230, and f(-7) produces
-6.  So:

    void g(void) {
        int i;    /* note lack of initializer */

        i = f(i); /* ERROR, UNPREDICTABLE */
        ...
    }

Suppose you attempt to catch this with:

    int f(int x) {
        if (x < 0 || x > 4)
            panic("f: x = %d: out of range", x);
        ++x;
        if (x >= 5)
            x -= 5;
        return x;
    }

This will in fact catch many "bad" calls to f() -- but in g(), if
the uninitialized i "just happens" to be 2, it will look, to f()
at least, like a perfectly valid value.

The same holds for pointers:

    void h(void) {
        char *p;   /* note lack of initializer */

        p = f2(p); /* ERROR, UNPREDICTABLE */
        ...
    }

Inside f2(), the pointer argument may well "look invalid" under
some (machine-dependent) inspection technique -- just as an out of
range value of x in f() can be discovered -- but it might also
"look valid", just as x might be equal to 2 despite being uninitialized.

Now, a good compiler may produce a warning for the call to f() in
g(), or the call to f2() in h, because the compiler can tell that
the variables in question (i and p respectively) have never been
assigned a value before their value is used.  No diagnostic is
*required*, but a good compiler should be able to provide one,
because the error is quite obvious even to a simple mechanical
analysis.

Unfortunately, if we start passing the addresses of the variables
(instead of their values), this simple analysis breaks down.  Here
is a revised f() and g(), for instance:

    void f2(int *xp) {
        int x = *xp;

        if (x < 0 || x > 4)
            panic("f: x = %d: out of range", x);
        ++x;
        if (x >= 5)
            x -= 5;
        *xp = x;
    }

    void g2(void) {
        int i;  /* note lack of initializer */

        f2(&i); /* ERROR, UNPREDICTABLE */
        ...
    }

Here the compiler can no longer use the trivial, local-only,
mechanical analysis technique to discover that the un-initialized,
non-existent value in "i" is being passed.  f2() gets a pointer to
i, so it is able to change i, so there are versions of f2() that
would make the call from g2() legal.  For instance, if we rewrite
f2() as:

    void f2(int *xp) { *xp = 42; }

the call in g2() is now "legal" or "correct".

There are languages (see Ada) in which one annotates one's function
parameters as to whether a reference ("pointer") is "in", "out",
or "in out": whether the original value is used ("in"), and whether
a new value is stored ("out").  If the original value is used *and*
a new value is stored, the parameter is "in out".  If C had this,
we might write:

    void f2(in out int *xp) {
        ...
    }

and then a good compiler *could* use simple local mechanical analysis
to produce a warning for g2().  But C does not have this, so if
you want good compilers that use only simple local mechanical
analysis to warn about uninitialized values of parameters, you must
take the actual values as arguments, rather than a pointer to the
variable that stores the value.

Of course, nothing says that a C compiler has to do simple local
mechanical analysis (or even be "good", for that matter).  A "very
good" compiler that does interprocedural analysis would be able to
discover that *xp is "in out" and warn you that the call from g2()
is invalid.  A "bad" compiler that does no analysis at all will
not warn you even with the "obvious" bad call to f() from g().
 
R

Richard Heathfield

Chad said:
Maybe I didn't think about this enough, but how can *ptr be a bad move.

If ptr is NULL, you're not pointing to a valid char * object, so you can't
dereference the pointer (to get the value of that non-existent object)
without invoking undefined behaviour.
 
N

Niklas Norrthon

int main()


Simple:

char *test = NULL;

If you ALWAYS declare pointers like this, you will have no problems.
The answer is simply to NEVER declare pointer without initialising it
to NULL. If you see anywhere in your code where you declare a pointer
that is not initialised to NULL consider is a BUG. It's only 8
characters including spacebars, why not just type it?

So where is the bug in this code?

#include <stdio.h>

/* pointer not initialised to NULL following... */
const char* msg = "This is a message.";

int main(void)
{
printf("%s\n", msg);
return 0;
}

/Niklas Norrthon
 
N

Niklas Norrthon

[ about allowing a function to handle both initialized and
uninitalized pointers ]
I wanted this method to be full proof to be used by other user. My
method should able to handle if any uninitialized variable is coming..

This is a problem that should be solved by design and documentation.

The design of your function dictates how it can be used, and the
documentation passes this information along to the programmers that
write code that calls the function.

In C it is impossible to determine if a variable has been properly
initialized by just looking at its value. This is a fact that we
have to live with, and it applies to all types not just pointers.

For non NULL pointers that are initialized in a proper way it is
also impossible to determine if they point to static, automatic,
or free store memory (globals, locals, or heap).

This means that a function that during the design of a function
taking pointer arguments it is necessary to determine what types
of pointers the function can accept, and what to do if wrong
kind of pointers are passed to the function. To see examples
of such design decisions one does only have to take a look at
the documentation of the standard library:

size_t strlen(const char* ptr):
Argument must be an initialized pointer to nul-terminated
string. Anything else leads to undefined behavior.

size_t strcpy(char* dest, const char* src):
First argument must be initialized to point to allocated memory
big enough to hold the string pointed to by the second arguemnt.
The second argument must point to a nul-terminated string.
Anything else leads to undefined behaviour

void free(void* ptr):
Argument must be NULL, or exactly the same as has previously
been returned by malloc, calloc or realloc (and not been passed
to free or realloc in between). Anything else is undefined
behavior.

It is perfectly acceptable to demand of a caller that pointer
parameters are of specific kinds, just make sure that it is
documented so that the programmer writing code calling the
function knows what the function expects.

/Niklas Norrthon
 

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
473,996
Messages
2,570,238
Members
46,826
Latest member
robinsontor

Latest Threads

Top