* 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).