Displaying a byte content given by an address - c

I have to display the content of n bytes starting in a specific memory address, i.e: an output for 25 bytes since 0x00004000 (segment text in virtual space) would be #include <stdio.h> #inclu (25 letters)
My idea was to assign to a char *c the address given, like: *c=address; and then printf("%s",c);. For me, conceptually makes sense and I know that in some cases it would cause a segmentation fault if the address is not valid.
However I have implemented it and it always causes a segmentation fault. I use pmap <pid> to know what areas can be displayed (low areas) of that process. When I say "areas that can be displayed" I mean text areas (code).
So, what I am doing wrong? is stupid the assignment *c=address; ?

char *c = address;
for (int i = 0; i < n; i++) {
putchar(c[i]);
}
Errors in your code
having something like
char *c;
*c = address;
Is invalid, because c is a dangling pointer (you have never initialized it). You want to set the address which c points to to address: c = address
printf("%s",c);
You don't know if c is a proper string, it may contain garbage or may not be n bytes length. That's why I used putchar

*c = address puts the value of address into the memory c currently points to. That is what the * is doing. To change where c points, use c = address.
But still, this sounds like a rather, ahem, suboptimal programming exercise.

Related

Why don't c compiler throws error if I try storing values greater than what I specified during dynamic allocation?

This is what I have tried. I have not even ended my string with a \0 character.
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int main()
{
int size=5;
char *str = (char *)malloc((size)*sizeof(char));
*(str+0) = 'a';
*(str+1) = 'b';
*(str+2) = 'c';
*(str+3) = 'd';
*(str+4) = 'e';
*(str+5) = 'f';
printf("%d %s", (int)strlen(str), str);
return 0;
}
According to the rule, it can store only 4 charaters and one for the \0 as I have specified it in malloc.
It gives me the perfect output.
Output
6 abcdef
Check this out here : https://onlinegdb.com/B1UeOXbjH
You allocated your own memory, so it is up to you to manage it responsibly. In your example, you allocated 5 bytes of RAM, and you created a pointer which points to the first address of it. Your pointer is not a string, it is not an array. So, what you then did was you wrote 6 bytes, starting at the address pointed to by your pointer. The 6th byte is overflowing into unallocated memory. So you wrote it into memory which may be used for something else and could cause unknown problems. You have created a leak, and you didn't free up the memory you allocated when you quit the program, which is another leak. You didn't add in a /0 anywhere so I honestly think you lucked out. There really isn't any way to know how strlen() would respond. If you want C to handle it for you, than you have char *str = "abcdef" and that will create your string of length 6 plus the /0. But if you do it manually like you did, than you have to handle everything.
C does not count its arrays: if you ask for a chunk of memory of so-many bytes, it gives you that chunk via a pointer, and it's entirely up to you to manage it responsibly.
This leads to a certain efficiency - no overhead from the compiler/runtime checking all this for you - but creates enormous challenges for incorrect code (which you've shown an example of).
Many of us every much like the down-to-the-metal efficiency of C, but there's a reason that so many prefer languages such as Java or C# that do manage this for you, and enforce array bounds. It's a tradeoff.

Pointers address location

As part of our training in the Academy of Programming Languages, we also learned C. During the test, we encountered the question of what the program output would be:
#include <stdio.h>
#include <string.h>
int main(){
char str[] = "hmmmm..";
const char * const ptr1[] = {"to be","or not to be","that is the question"};
char *ptr2 = "that is the qusetion";
(&ptr2)[3] = str;
strcpy(str,"(Hamlet)");
for (int i = 0; i < sizeof(ptr1)/sizeof(*ptr1); ++i){
printf("%s ", ptr1[i]);
}
printf("\n");
return 0;
}
Later, after examining the answers, it became clear that the cell (& ptr2)[3] was identical to the memory cell in &ptr1[2], so the output of the program is: to be or not to be (Hamlet)
My question is, is it possible to know, only by written code in the notebook, without checking any compiler, that a certain pointer (or all variables in general) follow or precede other variables in memory?
Note, I do not mean array variables, so all the elements in the array must be in sequence.
In this statement:
(&ptr2)[3] = str;
ptr2 was defined with char *ptr2 inside main. With this definition, the compiler is responsible for providing storage for ptr2. The compiler is allowed to use whatever storage it wants for this—it could be before ptr1, it could be after ptr1, it could be close, it could be far away.
Then &ptr2 takes the address of ptr2. This is allowed, but we do not know where that address will be in relation to ptr1 or anything else, because the compiler is allowed to use whatever storage it wants.
Since ptr2 is a char *, &ptr2 is a pointer to char *, also known as char **.
Then (&ptr2)[3] attempts to refer to element 3 of an array of char * that is at &ptr2. But there is no array there in C’s model of computation. There is just one char * there. When you try to refer to element of 3 of an array when there is no element 3 of an array, the behavior is not defined by the C standard.
Thus, this code is a bad example. It appears the test author misunderstood C, and this code does not illustrate what was intended.
char *ptr2 = some initializer;
(&ptr2)[3] = str;
When you evaluate &ptr2, you obtain the address of memory where is stored the pointer that points to that initializer.
When you do (&ptr2)[3]=something you try to write 3*sizeof(void*) locations further from the location of ptr2, the address of a string. This is invalid and almost sure it finishes with segmentation fault.
No, it's not possible and no such assumptions can be made.
By writing outside a variable's space, this code invokes undefined behavior, it's basically "illegal" and anything can happen when you run it. The C language specification says nothing about variables being allocated on a stack in some particular order that you can exploit, it does however say that accessing random memory is undefined behavior.
Basically this code is pretty horrible and should never be used, even less so in a teaching environment. It makes me sad, how people mis-understand C and still teach it to others. :/
A program usually is loaded in memory with this structure:
Stack, Mmap'ed files, Heap, BSS (uninitialized static variables), Data segment (Initialized static variables) and Text (Compiled code)
You can learn more here:
https://manybutfinite.com/post/anatomy-of-a-program-in-memory/
Depending on how you declare the variable it will go to one of the places said before.
The compiler will arrange the BSS and Data segment variables as he wishes on compilation time so usually no chance. Neither heap vars (the OS will get the memory block that fits better the space allocated)
In the stack (which is a LIFO structure) the variables are put one over eachother so if you have:
int a = 5;
int b = 10;
You can say that a and b will be placed one following the other. So, in this case you can tell.
There is another exception and that is if the variable is an structure or an array, they are always placed like i said before, each one following the last.
In your code ptr1 is an array of arrays of chars so it will follow the exception i said.
In fact, do the following exercise:
#include <stdio.h>
#include <string.h>
int main(){
const char * const ptr1[] = {"to be","or not to be","that is the question"};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < strlen(ptr1[i]); j++)
printf("%p -> %c\n", &ptr1[i][j], ptr1[i][j]);
printf("\n");
}
}
and you will see the memory address and its content!
Have a nice day.

Why does the execution of this basic program gives an error?

I don't really understand, why does the execution of this program give an error?
int main()
{
char *b;
*b='2';
printf("%c",*b);
return 0;
}
As it stands, b is uninitialized and thus may point to any arbitrary location. When you say *b =..., you are trying to write to some unspecified location, which (depending on what that location is) often causes an error (say a segfault). Perhaps you meant to declare b as a char instead of a pointer to one?
This looks like its taken straight from homework or a textbook. When you declare the char pointer b, it is not given a memory address (where it points to) by default, it just contains whatever was in the memory location beforehand. This means that if you attempt to work with the value (*b = '2' or printf) it will try to read this random information left over in memory as an address and look for a char at that address. This would cause a segmentation fault or if you're unlucky, it would grab garbage from the memory and use it as a char value.
The solution would be to create a char variable (char a) and set the pointer to the location of a (b = &a).
Hopefully this helps, and good luck on your studies.

C - Read value from a specific memory address

How do I read a value from a given memory address (e.g. 0xfed8213) using the C programming language?
Each process has its own virtual address space, so, address 0x12345678 in one program will not be the same as address 0x12345678 in another.
You can access what is at the address simply by doing:
#include <stdio.h>
int main(int argc, char *argv[]){
char *ptr = (char *)0x12345678; //the addr you wish to access the contents of
printf("%c\n", *ptr); //this will give you the first byte, you can add any more bytes you need to the ptr itself, like so: *(ptr + nbyte).
return 0;
}
You'll likely get a segmentation fault though, unless you really know what you're doing. My guess is that you think this is the way to solve some other problem, whereas this isn't the actual solution. This does answer your question in the OP, though.
Here is Another Virtual Memory learning resource.

Understanding memory access in C

Consider the following:
int i;
i = 12;
Which will obviously not give any errors. However, the following does:
int *i;
*i = 12;
Program received signal: “EXC_BAD_ACCESS”.
Why don't I have access to modify the integer? It's still in the process's address space right?
You don't allocate memory for the integer, you just create a pointer. I.e. when you try to access whatever the pointer points at to set the value, the pointer does not point to any valid allocated memory.
Understanding memory on this basic level is a necessity if you want to learn C. I suggest you buy an introduction to C book, or look up tutorials online. One of many places to start is here: http://www.cprogramming.com/tutorial/c-tutorial.html
You're missing a step. When you say:
int *i;
What you have is a pointer to an integer. Right now, it's not pointing to any integer in particular, which is why you can't dereference it and change the value. You'll need to set i to something:
int j = 5;
i = &j;
Now, i is a pointer that points to the value of j, which is 5. You can now change the value:
*i = 6; // j (which i points to) is now 6
To add to the answers already mentioned, you either need to point the pointer to something, or allocate memory for the pointer so that is has space in memory to point to. You can do this:
int *i;
i = malloc(sizeof(int));
if(i == NULL) // or if(i == 0) or if(NULL == i) or whatever you prefer
fprintf(stderr,"Some error blah blah\n")
*i = 5;
printf("i = %d\n",*i);
That would work as well. Just make sure if you use malloc to test for a null pointer after doing so, otherwise you could end up with problems later if for some strange reason you couldn't allocate the memory needed for an int.
No, when you declare a pointer without allocating memory to it, you are not guaranteed to point at a valid address in the address space of the process.
For example assume that it is a 32 bit pointer, your assumption would mean that every process has 4 GB of memory available. But you may not even have 4 GB physical memory in the computer.
What actually happens when you allocate memory is that the CPU, or the virtual memory hardware, is set up so it can translate the virtual address in your program into a physical memory address.
You can read a little more about virtual memory in wikipedia, see http://en.wikipedia.org/wiki/Virtual_memory

Resources