linux-c-programming.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Into the Void
@ 2005-01-26  0:09 Scott
  2005-01-26  2:18 ` Ron Michael Khu
  0 siblings, 1 reply; 12+ messages in thread
From: Scott @ 2005-01-26  0:09 UTC (permalink / raw)
  To: linux-c-programming

Years ago, I learned this trick from somebody in the C/C++ Journal, or
whatever that rag was called:

           memcpy(*data_buf,bp,len)[len] = '\0';

I get the following error:

indatax.c: In function `read_datum':
indatax.c:374: warning: dereferencing `void *' pointer
indatax.c:374: invalid use of void expression

and if I cast the function:

           (char *) memcpy(*data_buf,bp,len)[len] = '\0';

I get:

indatax.c: In function `read_datum':
indatax.c:374: warning: dereferencing `void *' pointer
indatax.c:374: void value not ignored as it ought to be

What aren't I understanding here? Tell me to go away if these
questions are too elementary for the list....

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Into the Void
  2005-01-26  0:09 Scott
@ 2005-01-26  2:18 ` Ron Michael Khu
  0 siblings, 0 replies; 12+ messages in thread
From: Ron Michael Khu @ 2005-01-26  2:18 UTC (permalink / raw)
  To: Scott, linux-c-programming

why dont u try casting the whole thing??
(putting an enclosing parenthesis on ur memcpy oper)

((char *) memcpy(*data_buf,bp,len))[len] = '\0';


Scott wrote:

>Years ago, I learned this trick from somebody in the C/C++ Journal, or
>whatever that rag was called:
>
>           memcpy(*data_buf,bp,len)[len] = '\0';
>
>I get the following error:
>
>indatax.c: In function `read_datum':
>indatax.c:374: warning: dereferencing `void *' pointer
>indatax.c:374: invalid use of void expression
>
>and if I cast the function:
>
>           (char *) memcpy(*data_buf,bp,len)[len] = '\0';
>
>I get:
>
>indatax.c: In function `read_datum':
>indatax.c:374: warning: dereferencing `void *' pointer
>indatax.c:374: void value not ignored as it ought to be
>
>What aren't I understanding here? Tell me to go away if these
>questions are too elementary for the list....
>-
>To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>  
>



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Into the Void
@ 2005-01-26 13:45 Jeff.Fellin
  2005-01-26 16:11 ` Scott
  0 siblings, 1 reply; 12+ messages in thread
From: Jeff.Fellin @ 2005-01-26 13:45 UTC (permalink / raw)
  To: drmemory; +Cc: linux-c-programming, linux-c-programming-owner


The reason you are getting the references to void is the function prototype
for memcpy is:

      memcpy (void *dest, void *src, size_t n);

You are passing char* pointers which are not void * pointers. You have to
correct your arguments
to remove the error messages. Please use man memcpy() for more details.


Jeff Fellin
RFL Electronics
Jeff.Fellin@rflelect.com
973 334-3100, x 327


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: Into the Void
@ 2005-01-26 16:02 Huber, George K RDECOM CERDEC STCD SRI
  0 siblings, 0 replies; 12+ messages in thread
From: Huber, George K RDECOM CERDEC STCD SRI @ 2005-01-26 16:02 UTC (permalink / raw)
  To: linux-c-programming

Scott wrote:

>Years ago, I learned this trick from somebody in the C/C++ Journal, or
>whatever that rag was called:
>
>           memcpy(*data_buf,bp,len)[len] = '\0';
>
>I get the following error:
>
>indatax.c: In function `read_datum':
>indatax.c:374: warning: dereferencing `void *' pointer
>indatax.c:374: invalid use of void expression

My first question would be what is the type of `data_buf'?

Secondly, as others have mentioned, the prototype for memcpy is:

void* memcpy(void* dest, const void* src, size_t len);

so you need to supply the address of a source buffer and the address
of a destination buffer.  The statement `*data_buf' can be thought of 
as saying "get the value stored in the memory location pointed to by
data_buf" (i.e. dereference data_buf).

From looking at your example, I take that what you are doing is copying 
data in `bp' to the buffer `data_buf' and then appending a null-terminator
to `data-buf'.  Assuming that data_buf and buf are properly declared and 
defined, the following should work:

       ((char*)memcpy((void*)data_buf, (const void*)bp, len))[len];

While your `trick' works, it probably is a maintenance nightmare - the 
intent is not immediately clear.  I would probably do the same thing in
two steps:

memset((void*)data_buf, '\0', len);                 // fills data_buf with nulls...
memcpy((void*)data_buf, (const void*)bd, len-1);    // copy the data...

Hope this helps,
George

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Into the Void
  2005-01-26 13:45 Jeff.Fellin
@ 2005-01-26 16:11 ` Scott
  2005-01-27  4:02   ` Ron Michael Khu
  0 siblings, 1 reply; 12+ messages in thread
From: Scott @ 2005-01-26 16:11 UTC (permalink / raw)
  To: linux-c-programming

On Wed, Jan 26, 2005 at 08:45:09AM -0500, Jeff.Fellin@rflelect.com wrote:
> 
> The reason you are getting the references to void is the function prototype
> for memcpy is:
> 
>       memcpy (void *dest, void *src, size_t n);
> 
> You are passing char* pointers which are not void * pointers. You have to
> correct your arguments
> to remove the error messages. Please use man memcpy() for more details.

So I should use

   memcpy ((void *) *data_buf, (void *) bp, len) [len] = '\0';

(len is already type size_t) 

Or, I guess, to follow Ron's suggestion too:

   ((char*) memcpy ((void *) *data_buf, (void *) bp, len)) [len] = '\0';

Just curious as to what evil all of this extra typing is supposed to
be protecting me from?

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Into the Void
  2005-01-26 16:11 ` Scott
@ 2005-01-27  4:02   ` Ron Michael Khu
  2005-01-27 17:01     ` Scott
  0 siblings, 1 reply; 12+ messages in thread
From: Ron Michael Khu @ 2005-01-27  4:02 UTC (permalink / raw)
  To: Scott, linux-c-programming

extra typing?? r u using the term "type" in the same context as "data 
type"(progamming language concept)?
or "type" in the sense "keyboard typing"??

>>So I should use
>> memcpy ((void *) *data_buf, (void *) bp, len) [len] = '\0';

Oops, I think u've misunderstood jeff's reply...
What jeff and the others are trying to say is that the return value of 
memcpy() is of type "void *"

In essence:
void *ptr;
ptr = memcpy(...)

thus, u need to cast the return value to something more appropriate.

And by the way, 
"memcpy ((void *) *data_buf, (void *) bp, len) [len] = '\0';" is WRONG

u still need to cast it properly if ur u persist on doing it the "one-liner way":
( (char*)memcpy ((void *) *data_buf, (void *) bp, len) )[len] = '\0';

*TAKE NOTE of the enclosing parenthesis:
((char*)SOMETHING)[index] ='\0'   

(assuming of course SOMETHING is something that could safely be treated as char *)

and like what George stated earlier... this one-liner thing is a maintenance 
headache(a code readability issue), and thus, not advisable.
better chop that one-liner down to something more readable/maintanable.

-Ron

P.S. Hmmmm... u seem to have trouble understanding what a "void*" is.
Void * could be anything.. thus u cant simply go around indexing a void*
and treating it like an array without properly casting it...



Scott wrote:

>On Wed, Jan 26, 2005 at 08:45:09AM -0500, Jeff.Fellin@rflelect.com wrote:
>  
>
>>The reason you are getting the references to void is the function prototype
>>for memcpy is:
>>
>>      memcpy (void *dest, void *src, size_t n);
>>
>>You are passing char* pointers which are not void * pointers. You have to
>>correct your arguments
>>to remove the error messages. Please use man memcpy() for more details.
>>    
>>
>
>So I should use
>
>   memcpy ((void *) *data_buf, (void *) bp, len) [len] = '\0';
>
>(len is already type size_t) 
>
>Or, I guess, to follow Ron's suggestion too:
>
>   ((char*) memcpy ((void *) *data_buf, (void *) bp, len)) [len] = '\0';
>
>Just curious as to what evil all of this extra typing is supposed to
>be protecting me from?
>-
>To unsubscribe from this list: send the line "unsubscribe linux-c-programming" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>  
>



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Into the Void
  2005-01-27  4:02   ` Ron Michael Khu
@ 2005-01-27 17:01     ` Scott
  0 siblings, 0 replies; 12+ messages in thread
From: Scott @ 2005-01-27 17:01 UTC (permalink / raw)
  To: linux-c-programming

On Thu, Jan 27, 2005 at 12:02:58PM +0800, Ron Michael Khu wrote:
> extra typing?? r u using the term "type" in the same context as "data 
> type"(progamming language concept)?
> or "type" in the sense "keyboard typing"??

The latter. Jeff was telling me that I had to cast all of the
arguments to (void *), rather than, as you correctly said, the return
value. It doesn't seem to me (or more importantly, to the compiler)
that casting the ARGUMENTS is necessary?

> 
> *TAKE NOTE of the enclosing parenthesis:
> ((char*)SOMETHING)[index] ='\0'   

I did get it right later in my post, didn't I?
> >Or, I guess, to follow Ron's suggestion too:
> >
> >  ((char*) memcpy ((void *) *data_buf, (void *) bp, len)) [len] = '\0';

> 
> P.S. Hmmmm... u seem to have trouble understanding what a "void*" is.
> Void * could be anything.. thus u cant simply go around indexing a void*
> and treating it like an array without properly casting it...

I'm starting to grok it. I learned C back in the old days before there
was such a thing, and you could pretty much do anything you wanted
with any pointer. Could sure shoot yourself in the foot if you weren't
paying attention! Actually, I suppose back then memcpy and the like
returned char*. To test my understanding: I have to cast the function
because of the indexing operation. If I just ASSIGN the return value,
then the compiler does implicit type-casting for me. As in:

  char *bp;
  bp = memcpy(foo,bar,len);

Thanks for your help; I actually managed to get the program to compile
with no errors, but now am getting a segmentation fault which I can't
track down, so I'll probably be back to plague you folks some more!

Scott.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: Into the Void
@ 2005-01-27 17:58 Huber, George K RDECOM CERDEC STCD SRI
  2005-01-28  4:36 ` Amit Dang
  0 siblings, 1 reply; 12+ messages in thread
From: Huber, George K RDECOM CERDEC STCD SRI @ 2005-01-27 17:58 UTC (permalink / raw)
  To: 'Scott', 'linux-c-programming@vger.kernel.org'

Scott wrote:

>Thanks for your help; I actually managed to get the program to compile
>with no errors, but now am getting a segmentation fault which I can't
>track down, so I'll probably be back to plague you folks some more!

Even without seeing your code, I probably can guess what is happening.
Consider the following sample program (with no error checking)

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

#define BUF_LEN 6

int main()
{
    char*   in_buf = malloc(BUF_LEN*sizeof(char));
    char*   out_buf = malloc(BUF_LEN*sizeof(char));

    strcpy(out_buf, "Test");

    ((char*)memcpy((void*)in_buf, out_buf, 4))[4] = '\0';
  
    printf("%s\n", in_buf);
   
    return 0;
}
======================================================================

The above program compiles cleanly and produces the expected output.

However, if the above program is changed to this:

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

#define BUF_LEN 6

int main()
{
    char*   in_buf = malloc(BUF_LEN*sizeof(char));
    char*   out_buf = malloc(BUF_LEN*sizeof(char));

    strcpy(out_buf, "Test");

    ((char*)memcpy((void*)*in_buf, out_buf, 4))[4] = '\0';
  
    printf("%s\n", in_buf);
   
    return 0;
}
======================================================================

we get a single warning (warning: cast to pointer from integer of 
different size) and the program segfaults when it is run.  

Make sure you are not dereferencing the the first parametere to memcpy.

Also, if the above does not help, try compiling with debugging support 
turned on (i.e. gcc -g ...) and then run the program under gdb.  Using the 
gdb `where' command will show you what line you are seg-faulting on.

Finally, I find it useful to alway compile using the flags "-ansi -pedantic 
-Wall" (or "-std=c99 -pedantic -Wall) and treat any warning as errors.  I 
know it can be a pain-in-the-arse, but I find that it does minimize run-time
errors.

George

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Into the Void
  2005-01-27 17:58 Huber, George K RDECOM CERDEC STCD SRI
@ 2005-01-28  4:36 ` Amit Dang
  0 siblings, 0 replies; 12+ messages in thread
From: Amit Dang @ 2005-01-28  4:36 UTC (permalink / raw)
  To: Huber, George K RDECOM CERDEC STCD SRI, linux-c-programming

Hi George, I was just going through the code. In second code, line
((char*)memcpy((void*)*in_buf, out_buf, 4))[4] = '\0';
why does (void *)*in_buf returns NULL. I tried typecasting different type of
pointers and its always NULL.

Regards,
Amit Dang

----- Original Message ----- 
From: "Huber, George K RDECOM CERDEC STCD SRI" <George.K.Huber@us.army.mil>
To: "'Scott'" <drmemory@3rivers.net>; <linux-c-programming@vger.kernel.org>
Sent: Thursday, January 27, 2005 11:28 PM
Subject: RE: Into the Void


> Scott wrote:
>
> >Thanks for your help; I actually managed to get the program to compile
> >with no errors, but now am getting a segmentation fault which I can't
> >track down, so I'll probably be back to plague you folks some more!
>
> Even without seeing your code, I probably can guess what is happening.
> Consider the following sample program (with no error checking)
>
> ======================================================================
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> #define BUF_LEN 6
>
> int main()
> {
>     char*   in_buf = malloc(BUF_LEN*sizeof(char));
>     char*   out_buf = malloc(BUF_LEN*sizeof(char));
>
>     strcpy(out_buf, "Test");
>
>     ((char*)memcpy((void*)in_buf, out_buf, 4))[4] = '\0';
>
>     printf("%s\n", in_buf);
>
>     return 0;
> }
> ======================================================================
>
> The above program compiles cleanly and produces the expected output.
>
> However, if the above program is changed to this:
>
> ======================================================================
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> #define BUF_LEN 6
>
> int main()
> {
>     char*   in_buf = malloc(BUF_LEN*sizeof(char));
>     char*   out_buf = malloc(BUF_LEN*sizeof(char));
>
>     strcpy(out_buf, "Test");
>
>     ((char*)memcpy((void*)*in_buf, out_buf, 4))[4] = '\0';
>
>     printf("%s\n", in_buf);
>
>     return 0;
> }
> ======================================================================
>
> we get a single warning (warning: cast to pointer from integer of
> different size) and the program segfaults when it is run.
>
> Make sure you are not dereferencing the the first parametere to memcpy.
>
> Also, if the above does not help, try compiling with debugging support
> turned on (i.e. gcc -g ...) and then run the program under gdb.  Using the
> gdb `where' command will show you what line you are seg-faulting on.
>
> Finally, I find it useful to alway compile using the flags
"-ansi -pedantic
> -Wall" (or "-std=c99 -pedantic -Wall) and treat any warning as errors.  I
> know it can be a pain-in-the-arse, but I find that it does minimize
run-time
> errors.
>
> George
> -
> To unsubscribe from this list: send the line "unsubscribe
linux-c-programming" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: Into the Void
@ 2005-02-01 15:32 Huber, George K RDECOM CERDEC STCD SRI
  2005-02-02 12:15 ` Glynn Clements
  0 siblings, 1 reply; 12+ messages in thread
From: Huber, George K RDECOM CERDEC STCD SRI @ 2005-02-01 15:32 UTC (permalink / raw)
  To: 'Amit Dang', linux-c-programming

Amit wrote:

>Hi George, I was just going through the code. In second code, line
>((char*)memcpy((void*)*in_buf, out_buf, 4))[4] = '\0';
>why does (void *)*in_buf returns NULL. I tried typecasting different type of
>pointers and its always NULL.

Because it is NULL :-).

Seriously, lets forget about type-casting for a moment and just concentrate 
on the first term as written:

         *in_buf

Now consider what this means.  In english, we would read this as "dereference 
in_buf", or in other words "get the value in the memory address that is 
contained in the variable in_buf".  But what memory address does in_buf
contain, and more importaintly what is stored at the memory address?

In the code, I wrote this:

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

#define BUF_LEN 6

int main()
{
    char*   in_buf = malloc(BUF_LEN*sizeof(char));
    char*   out_buf = malloc(BUF_LEN*sizeof(char));
    strcpy(out_buf, "Test");
    ((char*)memcpy((void*)*in_buf, out_buf, 4))[4] = '\0';
...
=======================================================================

So we see that in_buf contains the address of a memory location that will
hold a character, pictorially (excuse the ASCII art, and assuming that the 
size of a character is one byte).

       2004   2005   2006   2007   2008   2009    <---- hypothetical addresses
      +------+------+------+------+------+------+
      |  1   |      |      |      |      |      |
      | byte |      |      |      |      |      |
      +------+------+------+------+------+------+
      ^
      |
      |
      in_buf

So from the picture, in_buf would contain the value of `2004' and *in_buf 
would be asking for the value currently in memory location 2004.  But what 
is in there?  Well we have not put anything in that memory location yet, and
as I recall, under Linux any memory is zero-out when returned by malloc to
help prevent information leakage from one application to another.  So while
we have not put anything in that memory address, malloc has initialized it
to 0 for us.  Thus *in_buf will return zero (and since NULL is 0, we can 
also think of getting NULL).

Now with this, lets think about the original line of code:

   ((char*)memcpy((void*)*in_buf, out_buf, 4))[4] = '\0';

and lets think about what happens when this line is executed.  First *in_buf
is evaluated and returns NULL (or 0).  This is then type-cast into a void 
pointer (remembering that NULL is a valid pointer value so the type cast 
works just fine).  Finally the contents of memory starting at out_buf is 
attempeted to be copied to the memory location starting at 0 - thus the 
segmentation fault.

Finally, consider the warning that compiling the code gives:

warning: cast to pointer from integer of different size

Lets see if we can understand where this is coming from.  First, under IA-32 Linux
pointers are 32-bit unsigned integer values.  Now when we do a dereference on in_buf
we get back a single byte (assuming characters a single byte quantities) or an 8-bit
vaule.  So the expression `(void*)*in_buf' is attempting to take an 8-bit value and
make it a 32-bit pointer.  The converion 8-bit integer to 32-bit integer is allowed and 
will happen transparently (in most cases) because there is not loss of data.  However 
the compiler is warning us that in this case a pointer is involved which is 
probably not what we want. 

Hope this helps,
George

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: Into the Void
  2005-02-01 15:32 Into the Void Huber, George K RDECOM CERDEC STCD SRI
@ 2005-02-02 12:15 ` Glynn Clements
  0 siblings, 0 replies; 12+ messages in thread
From: Glynn Clements @ 2005-02-02 12:15 UTC (permalink / raw)
  To: linux-c-programming


Huber, George K RDECOM CERDEC STCD SRI wrote:

> Well we have not put anything in that memory location yet, and
> as I recall, under Linux any memory is zero-out when returned by malloc to
> help prevent information leakage from one application to another.

Memory contains zeroes when it is first given to the process by the
kernel. Whether or not memory returned from malloc() contains zeroes
depends upon whether that memory has been used previously by the
current process.

At the beginning of a process' life cycle (e.g. at the top of main()),
memory returned from malloc() is likely to contain zeroes.

As time goes by, it becomes increasingly likely that memory returned
from malloc() has previously been allocated, used, then free()d. In
which case, the memory's contents will have been retained; neither
malloc() nor free() themselves fill the memory with zeroes.

If you need to ensure that memory contains zeroes, either use calloc()
(which is defined to fill the memory with zeroes), or fill it yourself
with memset().

-- 
Glynn Clements <glynn@gclements.plus.com>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: Into the Void
@ 2005-02-02 18:17 Huber, George K RDECOM CERDEC STCD SRI
  0 siblings, 0 replies; 12+ messages in thread
From: Huber, George K RDECOM CERDEC STCD SRI @ 2005-02-02 18:17 UTC (permalink / raw)
  To: 'Glynn Clements', linux-c-programming



-----Original Message-----
From: Glynn Clements [mailto:glynn@gclements.plus.com]
Sent: Wednesday, February 02, 2005 7:16 AM
To: linux-c-programming@vger.kernel.org
Subject: RE: Into the Void

Glynn wrote:

>Huber, George K RDECOM CERDEC STCD SRI wrote:

>> Well we have not put anything in that memory location yet, and
>> as I recall, under Linux any memory is zero-out when returned by malloc to
>> help prevent information leakage from one application to another.

>Memory contains zeroes when it is first given to the process by the
>kernel. Whether or not memory returned from malloc() contains zeroes
>depends upon whether that memory has been used previously by the
>current process.

Agreed.

I was thinking of the case where there are multiple processes running at a time.  Each
process has it quanta `on the' processor and then another is swapped in.  I do not 
recall ever hearing if on a switch from one process to another if memory is reset or if 
the pages are just swapped back in.

Any one have information on this?

George

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2005-02-02 18:17 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-02-01 15:32 Into the Void Huber, George K RDECOM CERDEC STCD SRI
2005-02-02 12:15 ` Glynn Clements
  -- strict thread matches above, loose matches on Subject: below --
2005-02-02 18:17 Huber, George K RDECOM CERDEC STCD SRI
2005-01-27 17:58 Huber, George K RDECOM CERDEC STCD SRI
2005-01-28  4:36 ` Amit Dang
2005-01-26 16:02 Huber, George K RDECOM CERDEC STCD SRI
2005-01-26 13:45 Jeff.Fellin
2005-01-26 16:11 ` Scott
2005-01-27  4:02   ` Ron Michael Khu
2005-01-27 17:01     ` Scott
2005-01-26  0:09 Scott
2005-01-26  2:18 ` Ron Michael Khu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).