I want to print out things from given memory addresses.
Using this code, I can define a variable, define a pointer to it and print its contents using the pointer.
char buf[100];
void *p = buf;
strcpy(p, "Test string");
printf("Address: %X\n", &buf);
printf("Contents: %c\n", p);
What I want to do is to specify a certain memory address, and print out the contents of that block. I tried experimenting by incrementing and decremeting p, but it doesn't print out anything.
An interesting little problem. One that should occur to every programmer sooner or later, either out of curiosity or cussedness.
Essentially four parts.
Express the address you want as an integer of the appropriate size.
Cast the integer into a pointer to some type.
Dereference the pointer to get a value of that type.
Print the value.
[if desired, increment address and repeat.]
For simplicity I'll use an address of 0x1000 and integer contents.
int address = 0x1000;
int* pcontent = (int*)address;
int content = *pcontent;
printf ("Address %p: content %08x\n", pcontent, content);
Two points should be made.
This is undefined behaviour, but inevitable if you want to get a result.
The address I chose could be valid memory or could trigger a trap error or it could do just about anything. You'll have to experiment with different addresses to find out which.
[Many years ago I used this strategy to print out the entire contents of memory on a machine that had just 96KB of memory, which led to some interesting hacking possibilities. But I digress.]
You are using wrong specifier to print the address. Use %p and cast argument to void *.
printf("Address: %p\n", (void*)buf);
and to print string
printf("Contents: %s\n", p);
You have to define pointer p as
char *p = buf;
or to use casting then incrementing p. For example
p = ( char *)p + n;
For example
printf( "%s\n", ( char *)p + 5 );
You may not increment/decrement pointers of type void * because void in incomplete type.
Also the format specifiers in these calls
printf("Address: %X\n", &buf);
printf("Contents: %c\n", p);
are wrong.
If you want to print out a string you have to specify %s. if you wnat to print only one character then you should write
char *p = buf;
printf("Contents: %c\n", p[0]);
or
void *p = buf;
printf("Contents: %c\n", ( ( char *)p )[0]);
You are using %c instead use %s to print string printf("Contents: %s\n", p);
If we wanted to print random bytes from around memory, we would want to use:
char *p = buf;
printf("Address: %p\n", p);
printf("Contents: 0x%02x\n", *p);
Let's note though, that given a random address, dereferencing it can cause the application to fail. You can not assume that all of the memory space is valid.
You could try something like this:
void printMemory(void* mem, int bytes){
char* p = (char*) mem;
for(int i=0;i<bytes;i++){
printf("%x ",p[i] & 0xff);
if(i%8 == 7)
printf("\n");
}
}
This will print 8 bytes per row.
Related
char *s, *p = s;
size_t len = 0;
while (str[len++]);
s = malloc(sizeof(*s) * (len + 1));
How come here: char *s, *p = s; gives warning, but s is going to be initialized with malloc later.
chl/string.c:9:15: warning: āsā may be used uninitialized in this function [-Wmaybe-uninitialized]
9 | char *s, *p = s;
^
Since p is a pointer, pointing to s, won't p be updated as well when it points to s when s will be memory allocated?
Why would I have to do this instead:
char *s, *p;
size_t len = 0;
while (str[len++]);
s = malloc(sizeof(*s) * (len + 1));
p = s;
I thought pointers can change to what it points to, so why isn't p being updated as a pointer? Or if I'm seeing this wrong, why can't I just do *p = s, because s soon is going to be initialized, and p will point to s, so won't p update too?
Let's break this down a little.
What you have essentially is this:
char *s;
char *p = s;
s = malloc(...);
You're proposing that when s gets initialized (by malloc's return value), the value of p should also update.
But, as you've discovered this is not the case. Initially, when you do char *s, s can point to anything. It is not yet initialized.
Subsequently, when you do char *p = s;, you are assigning the current value of s to p -- which could be anything.
If you change the value of s, that doesn't automatically change the value of p. They are distinct variables. They are both pointers - but that doesn't mean they should point to the same thing just because one was initialized from the other.
There is no intrinsic link between these two pointers, even if you assign one to the other. The point is, even if they do point to the same thing at one point in time, you can change what one points to in the future without affecting the other.
Its actually no different from assigning to a non-pointer variable and asserting that it should be updated automatically, e.g.
int i;
int j;
i = j;
j = 5;
printf("%d\n", i); // Prints rubbish
printf("%d\n", j); // Prints 5
Here, j is initialized and the printf is as expected. Meanwhile, i was initialized from j's rubbish value -- the value that happened to be lying in memory at j's location (and that could be anything). Yet, I doubt anyone would suggest that i should "automatically" update in this case.
UPDATE:
The following update is in response to this followup comment made:
Here's why I thought it would update.. char *s = malloc(100); char *p
= s; see this, right? p[0] = 'e' for example will also change s[0], so I thought that since if assigning the element of p by index would also
change the element of s by index, there would be change/update, right?
How come p[0] = 'e' changes the element of both s and p, even though p
just assigned the current value of malloc? They are different pointers
but point to the same memory block, that's why! Am I right?
In this example, p and s again point to the same memory. When you do the assignment p[0] = 'e', you are NOT changing p or s -- you are in fact changing the value pointed to by p. And, since p and s point to the same memory, the change you've made will be visible through both p and s -- when you dereference either. Below is an in-depth example - I recommend compiling it and running it to see what gets printed, and read the comments which explain what is happening at each step.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
// this initializes s to point to some block of memory, e.g. address 0x560890f49260 when I run it locally
// it can store 100 bytes (chars) of data
char *s = malloc(100);
// this initializes p to point to the same block of memory as s => 0x560890f49260
char *p = s;
// this prints out the value of p and s
// they are of type 'pointer', so use %p
// this shows their address as being the same
printf("This is where p points to: %p\n", p);
printf("This is where s points to: %p\n", s);
// this sets the 1st byte at the location pointed to by p
// the thing we're changing is at address 0x560890f49260
// this "array" notation is just syntactic sugar for dereferencing a pointer - see below
p[0] = 'e';
// but p and s are unchanged
printf("This is where p points to: %p\n", p);
printf("This is where s points to: %p\n", s);
// this also changes the 1st byte (same as *p = 'e' and p[0] = 'e')
// here we're using the dereferencing syntax explictly
*(p + 0) = 'e';
// and p and s are still the same
printf("This is where p points to: %p\n", p);
printf("This is where s points to: %p\n", s);
// this changes the 2nd byte (same as p[1] = 'f')
// the thing we're changing is at address 0x560890f49261 - i.e. the next byte
*(p + 1) = 'f';
// and p and s still haven't changed
printf("This is where p points to: %p\n", p);
printf("This is where s points to: %p\n", s);
// this prints the 1st and 2nd byte pointed to by p and s
// they show the same thing in both cases - since p and s point to the same thing
printf("First byte pointed to by p: %c\n", p[0]);
printf("First byte pointed to by s: %c\n", s[0]);
printf("Second byte pointed to by p: %c\n", p[1]);
printf("Second byte pointed to by s: %c\n", s[1]);
// now p is pointing to something new, e.g. address 0x5617ba3ef6e0 when I run it locally
p = malloc(100);
// we see that p **HAS** changed, but s has **NOT** changed
// they are now pointing to different things
printf("This is where p points to: %p (new location!)\n", p);
printf("This is where s points to: %p (old location!)\n", s);
// this sets the 1st byte pointed to by p to be 'g'
p[0] = 'g';
// we can see that the 1st byte pointed to by p is 'g'
printf("First byte pointed to by p: %c\n", p[0]);
// while the first byte pointed to be s is unaffected
// since p and s point to different things
printf("First byte pointed to by s: %c\n", s[0]);
// always free your memory
free(p);
free(s);
return 0;
}
Oh no, p is not pointing to s.
Your statement:
char *p = s;
It's saying "copy the value of pointer s, into pointer p", so whatever may be the address stored in s (which is not initialized) it's what's going to be the value stored in p.
Once s is assigned the value of the malloc, p will remain with the initial value and s will be different.
I am trying to create a pointer to an address in memory given by the user, but I am having problems. I actually manage to create the pointer and print its address, but I never succeed to print or change its content. Would any one kindly explain why?
Here is the code I'm trying to run:
int m = 10;
printf("&m = %d (address in dec.)\n", &m);
printf("Enter an address: ");
int address;
scanf("%d", &address);
int* p = (int*) address;
printf("p = %d (address in dec.)\n", p);
printf("*p = %d (value)\n", *p);
and here is a console of me interacting with the program:
&m = 1220033252 (address in dec.)
Enter an address: 1220033252
p = 1220033252 (address in dec.)
Segmentation fault
Same thing happens if I try an address different from &m.
Thanks!
int is not necessarily big enough to hold a pointer. It's usually 32 bits, but pointers are 64 or 128 bits on many systems now.
You can use the built-in typedef intptr_t to declare an integer big enough to hold a pointer to integer.
int m = 10;
printf("&m = %" PRIiPTR " (address in dec.)\n", (intptr_t)&m);
printf("Enter an address: ");
intptr_t address;
scanf("%" SCNiPTR, &address);
int* p = (int*) address;
printf("p = %" PRIiPTR " (address in dec.)\n", (intptr_t)p);
printf("*p = %d (value)\n", *p);
For more information, see Why / when to use `intptr_t` for type-casting in C? and string format for intptr_t and uintptr_t
Shortly, you're hitting the fact that int and int * aren't the same types.
First, %d should be used for values of type int, which as not the same as pointer type. Most likely, on your machine size of pointer is bigger than size of int, so you are printing not the pointer, but just a part of it. For example, in my case the pointer value is 140734913221608 (0x7fff668293e8), but 1719833576 (0x668293e8) gets printed. Because of that, you enter a pointer to a random unallocated memory, and when you dereference it, segmentation fault occurs.
Second, the code for reading pointer value has the same problem. Additionally to wrong format string for scanf, you are trying to store the value in a variable of type int. A variable of pointer type should be used instead.
As for getting the code working, check out Correct format specifier to print pointer or address? for an in-depth explanation.
I have written a code which at first creates a memory alloc and save a string in an other pointer. According to the code, the value must be kept in an other address after free but it gives an error "munmap_chunk(): invalid pointer".
My Code is :
#include <stdio.h>
#include <stdlib.h>
#include "testfunc.h"
#include <string.h>
int main()
{
static char *server_alg;
char *test;
char *test = (char*) malloc(30*sizeof(char));
server_alg = "A";
strcpy(test, server_alg);
printf("server_alg addr = %u \n", &*server_alg);
printf("server_alg value = %u \n", server_alg);
printf("SERVER_ALGO addr = %d \n", *server_alg);
free(server_alg);
server_alg=NULL;
printf(" nulled \n");
printf("server_alg addr = %u \n", &*server_alg);
printf("server_alg value = %u \n", server_alg);
printf("SERVER_ALGO addr = %u \n", test);
printf("SERVER_ALGO value = %u \n", *test);
return 0;
}
Is it wrong?
Thx for your helps
You are freeing server_alg, but you didn't allocate any memory there. Instead, you assigned a string literal to it, so it's pointing to a read-only location in your program's binary:
server_alg = "A";
After this, you copy from that pointer to test:
strcpy(test, server_alg);
This is correct, as you properly allocated memory for test here:
char *test = (char*) malloc(30*sizeof(char));
Then, however, you try to free it while it is still pointing to "A" in your binary:
free(server_alg);
Instead, try freeing test, because that is pointing to the memory you allocated:
free(test);
test=NULL;
Furthermore, there's an issue with redeclaration here:
char *test;
char *test = (char*) malloc(30*sizeof(char));
You're defining test twice, best just remove that first line.
Last but not least, I'd change the prints in the end to:
printf("server_alg addr = %p \n", server_alg); // 00D87B30 (or something similar)
printf("server_alg value = %s \n", server_alg); // A
printf("SERVER_ALGO addr = %p \n", test); // 00000000
//printf("SERVER_ALGO value = %u \n", *test);
%s is the specifier that lets you print a string, and %p is the one for pointers. I commented out that last print because it would crash the program as test is freed and set to a null pointer now, so we can't access its content.
On another note, when you want to copy a string to the heap (be it from a string literal or from a different place on the stack heap), strdup can be used to do that. It allocates the appropriate amount of memory so you don't have to worry about that. Call it like this:
char *test = strdup("A");
When you're done with it, you free it by calling free(test);, just like with memory allocated by malloc.
following statements are the issues here
free(server_alg);
you can use free() only when if you allocate memory using one of malloc(), calloc() or realloc() as you have not allocated memory free(server_alg); is wrong, it will lead to memory dump
and we should never try to use pointer once we do free() on it.
I know there's tons of these and it's probably a simple question, but I can't seem to figure it out :(
char * char_buffer = (char *) malloc(64);
printf("%x\n", char_buffer);
memset(char_buffer,
0,
64);
printf("%x\n", char_buffer);
Output :
50000910
50000910
Why isn't char_buffer zero'd? Can someone explain what's happening?
You are confused about the difference between a pointer and space being pointed to.
Your code doesn't zero the pointer. It zeroes the space being pointed to. The memset function behaves that way. In fact you would not want to zero the pointer, as then it would no longer point to the memory you allocated.
Your printf statement attempts to print the pointer's value, which is the address of the space being pointed to. Not the contents of the space being pointed to.
Actually the printf statement causes undefined behaviour, because you mismatched format specifiers. Your compiler should have warned about this.
Here is some correct code:
printf("The buffer's address is %p\n", char_buffer);
printf("The buffer contains: %02X %02X %02X ...\n",
(unsigned char)char_buffer[0],
(unsigned char)char_buffer[1],
(unsigned char)char_buffer[2]);
To use the %X specifier you must pass non-negative values in, which is why the cast is necessary. You could declare the buffer as unsigned char * instead, in which case the cast would not be necessary.
You're printing the address of the buffer, not its contents. The contents are zero after the memset(). Just try:
printf("%d", char_buffer[0]);
and see the zero ;)
You're printing out the pointer, not the buffer values.
memset(p,v,n) writes the byte v to the byte pointed at by p and n-1 bytes after it. It doesn't touch the pointer p at all (it's passed in by value, how can it?)
To print out the buffer, you'd have to loop through it. I use something like this:
void printbuf(char *buf, int size)
{
int i = 0;
char b = 0;
for (i = 0; i < size; i++) {
if (i % 8 == 0) {
printf("\n%3d: ", i);
}
b = buf[i];
printf("%2hhX ", b);
}
}
I executed the following code.
#include <stdio.h>
int main()
{char *a="awake";
printf("%s\n", *(a+1));
return 0; // expected out_put to be wake
}
You're dereferencing the pointer, which makes it a char but trying to output a string. Change your print statement to printf("%s\n", a+1);
*(a+1) is the same as a[1] which is a char, not the char * that printf expects for the %s.
EDIT: clarification: printf needs an address for the %s specifier, a+1 is such an address (namely the address of the second character in the string), but *(a+1) then gives the value at that address. Which is just a character and in all likelyhood not a valid memory location for printf to read.
You don't want to defrefeence the char *:
printf("%s\n", (a+1));
does what you want.