Related
I posted a question about some pointer issues I've been having earlier in this question:
C int pointer segmentation fault several scenarios, can't explain behaviour
From some of the comments, I've been led to believe that the following:
#include <stdlib.h>
#include <stdio.h>
int main(){
int *p;
*p = 1;
printf("%d\n", *p);
return 0;
}
is undefined behaviour. Is this true? I do this all the time, and I've even seen it in my C course.
However, when I do
#include <stdlib.h>
#include <stdio.h>
int main(){
int *p=NULL;
*p = 1;
printf("%d\n", *p);
return 0;
}
I get a seg fault right before printing the contents of p (after the line *p=1;). Does this mean I should have always been mallocing any time I actually assign a value for a pointer to point to?
If that's the case, then why does char *string = "this is a string" always work?
I'm quite confused, please help!
This:
int *p;
*p = 1;
Is undefined behavior because p isn't pointing anywhere. It is uninitialized. So when you attempt to dereference p you're essentially writing to a random address.
What undefined behavior means is that there is no guarantee what the program will do. It might crash, it might output strange results, or it may appear to work properly.
This is also undefined behaivor:
int *p=NULL;
*p = 1;
Because you're attempting to dereference a NULL pointer.
This works:
char *string = "this is a string" ;
Because you're initializing string with the address of a string constant. It's not the same as the other two cases. It's actually the same as this:
char *string;
string = "this is a string";
Note that here string isn't being dereferenced. The pointer variable itself is being assigned a value.
Yes, doing int *p; *p = 1; is undefined behavior. You are dereferencing an uninitialized pointer (accessing the memory to which it points). If it works, it is only because the garbage in p happened to be the address of some region of memory which is writable, and whose contents weren't critical enough to cause an immediate crash when you overwrote them. (But you still might have corrupted some important program data causing problems you won't notice until later...)
An example as blatant as this should trigger a compiler warning. If it doesn't, figure out how to adjust your compiler options so it does. (On gcc, try -Wall -O).
Pointers have to point to valid memory before they can be dereferenced. That could be memory allocated by malloc, or the address of an existing valid object (p = &x;).
char *string = "this is a string"; is perfectly fine because this pointer is not uninitialized; you initialized it! (The * in char *string is part of its declaration; you aren't dereferencing it.) Specifically, you initialized it with the address of some memory which you asked the compiler to reserve and fill in with the characters this is a string\0. Having done that, you can safely dereference that pointer (though only to read, since it is undefined behavior to write to a string literal).
is undefined behaviour. Is this true?
Sure is. It just looks like it's working on your system with what you've tried, but you're performing an invalid write. The version where you set p to NULL first is segfaulting because of the invalid write, but it's still technically undefined behavior.
You can only write to memory that's been allocated. If you don't need the pointer, the easiest solution is to just use a regular int.
int p = 1;
In general, avoid pointers when you can, since automatic variables are much easier to work with.
Your char* example works because of the way strings work in C--there's a block of memory with the sequence "this is a string\0" somewhere in memory, and your pointer is pointing at that. This would be read-only memory though, and trying to change it (i.e., string[0] = 'T';) is undefined behavior.
With the line
char *string = "this is a string";
you are making the pointer string point to a place in read-only memory that contains the string "this is a string". The compiler/linker will ensure that this string will be placed in the proper location for you and that the pointer string will be pointing to the correct location. Therefore, it is guaranteed that the pointer string is pointing to a valid memory location without any further action on your part.
However, in the code
int *p;
*p = 1;
p is uninitialized, which means it is not pointing to a valid memory location. Dereferencing p will therefore result in undefined behavior.
It is not necessary to always use malloc to make p point to a valid memory location. It is one possible way, but there are many other possible ways, for example the following:
int i;
int *p;
p = &i;
Now p is also pointing to a valid memory location and can be safely dereferenced.
Consider the code:
#include <stdio.h>
int main(void)
{
int i=1, j=2;
int *p;
... some code goes here
*p = 3;
printf("%d %d\n", i, j);
}
Would the statement *p = 2; write to i, j, or neither? It would write to i or j if p points to that object, but not if p points somewhere else. If the ... portion of the code doesn't do anything with p, then p might happen point to i, or j, or something within the stdout object, or anything at all. If it happens to point to i or j, then the write *p = 3; might affect that object without any side effects, but if it points to information within stdout that controls where output goes, it might cause the following printf to behave in unpredictable fashion. In a typical implementation, p might point anywhere, and there will be so many things to which p might point that it would be impossible to predict all of the possible effects of writing to them.
Note that the Standard classifies many actions as "Undefined Behavior" with the intention that many or even most implementations will extend the semantics of the language by documenting their behavior. Most implementations, for example, extend the meaning of the << operator to allow it to be used to multiply negative numbers by power of two. Even on implementations that extend the language to specify that an assignment like *p = 3; will always perform a word-sized write of the value 3 to the indicated address, with whatever consequence results, there would be relatively few platforms(*) where it would be possible to fully characterize all possible effects of that action in cases where nothing is known about the value of p. In cases where pointers are read rather than written, some systems may be able to offer useful behavioral guarantees about the effect of arbitrary stray reads, but not all(**).
(*) Some freestanding platforms which keep code in read-only storage may be able to uphold some behavioral guarantees even if code writes to arbitrary pointer addresses. Such behavioral guarantees may be useful in systems whose state might be corrupted by electrical interference, but even when targeting such systems writing to a stray pointer would never be useful.
(**) On many platforms, stray reads will either yield a meaningless value without side effects or force an abnormal program termination, but on an Apple II which a Disk II card in the customary slot-6 location, if code reads from address 0xC0EF within a second of performing a disk access, the drive head to start overwriting whatever happens to be on the last track accessed. This is by design (software that needs to write to the disk does so by accessing address 0xC0EF, and having hardware respond to both reads and writes required one less logic gate--and thus one less chip--than would be required for hardware that only responded to writes) but does mean that code must be careful not to perform any stray reads.
I know that,in const int *ptr we can change the address but cannot change the value. i.e., ptr will be stored in read-write section(stack) and the object or entity will be stored in read-only section of data segement. So, we can change the address pointing by that pointer ptr, but cannot change the object which is constant.
int main()
{
const int *ptr=500;
(*ptr)++;
printf("%d\n",*ptr);
}
output is is assign the read only location to *ptr
int main()
{
const int *ptr=500;
ptr++;
printf("%d\n",*ptr);
}
No compilation errors, but at runtime the output is "segmentation fault".
I agree with the first one., why I am getting an segmentation fault in 2nd one? Where exactly they will be stored?
The reason for the segmentation fault is different from what you think.
It is not because of const.
It is because you are not allowed to access the area that you are trying to access when doing *ptr
When you make a pointer to "something", you are still not allowed to access the data (aka dereference the pointer) until you have made the pointer point to some memory that belongs to you.
Example:
int x = 0;
int* p = (int*)500;
int a = *p; // Invalid - p is not pointing to any memory that belongs to the program
p = &x;
int b = *p; // Fine - p is pointing to the variable x
p++;
int c = *p; // Invalid - p is not pointing to any memory that belongs to the program
The "invalid" code may give a segmentation fault. On the other hand, it may also just execute and produce unexpected results (or even worse: produce the expected result).
Lots of confusion here.
and the object or entity will be stored in read-only section of data segement
No, there is no requirement for where the pointed-at object is stored. This is only determined by any qualifiers/specifiers such as const or static, when declaring the pointed-at object.
const int *ptr=500;
This is not valid C and the code must result in a compiler message. An integer cannot get assigned to a pointer, there must be a conversion in between. GCC has a known flaw here, you have to configure it to be a standard compiler. gcc -std=c11 -pedantic-errors.
If you had code such as const int *ptr=(int*)500; which is valid C, then it would set the pointer to point at address 500. If there is an int at address 500, the code will work fine. If there is no memory there that you are allowed to access, then you will get some implementation-defined behavior like a crash - memory mapping is beyond the scope of the language.
(*ptr)++;
This is not valid C and the code must result in a compiler message. You are not allowed to modify a read-only location.
Overall, your compiler seems very poorly configured. GCC, correctly configured, gives 2 compiler errors.
const int *ptr=500; // WRONG
This declare a local variable which is a pointer to some constant integer. The const just tells the compiler that it is not allowed to update (overwrite) the dereferenced pointer memory cell.
However, your code is not correct; you probably want:
const int *ptr = (const int*)500;
The pointer is initialized to address 500 (you initialize the pointer).
On most systems, that address (and the following ones, e.g. at address 504 since sizeof(int) is 4) is out of the virtual address space. So dereferencing it (with *ptr) is undefined behavior and would often give some segmentation fault. See also this.
ptr will be stored in read-write section(stack) and the object or entity will be stored in read-only section of data segement.
This is wrong. Nothing is done at compilation time to keep the memory zone in a read-only text segment (however, most compilers are putting most literals or const static or global data -defined at compile-time- in it). Just you forbid the compiler to update the pointed thing (without cast).
If you need a read-only memory zone at runtime, you need to ask your OS for it (e.g. using mmap(2) & mprotect(2) on Linux). BTW protection works in pages.
On Linux, use pmap(1) (or proc(5), e.g. read sequentially the pseudo file /proc/self/maps from your program). You may want to add
char cmdbuf[64];
snprintf(cmdbuf, sizeof(cmdbuf), "pmap %d", (int) getpid());
system(cmdbuf);
before any dereference of ptr in your code to understand what is its virtual address space.
Try
cat /proc/self/maps
and
cat /proc/$$/maps
and understand their output (notice that $$ is expanded to the pid of your shell). Maybe experiment also strace(1) on your faulty program (which you should compile with gcc -Wall -g).
i am just started learning pointers in c. I have following few doubts. If i find the answers for the below questions. It Will be really useful for me to understand the concept of pointers in c. Thanks in advance.
i)
char *cptr;
int value = 2345;
cptr = (char *)value;
whats the use of (char *) and what it mean in the above code snippet.
ii)
char *cptr;
int value = 2345;
cptr = value;
This also compiles without any error .then whats the difference between i & ii code snippet
iii) &value is returning address of the variable. Is it a virtual memory address in RAM? Suppose another c program running in parallel, will that program can have same memory address as &value. Will each process can have duplicate memory address same as in other process and it is independent of each other?
iv)
#define MY_REGISTER (*(volatile unsigned char*)0x1234)
void main()
{
MY_REGISTER=12;
printf("value in the address tamil is %d",(MY_REGISTER));
}
The above snippet compiled successfully. But it outputs segmentation fault error. I don't know what's the mistake I am doing. I want to know how to access the value of random address, using pointers. Is there any way? Will program have the address 0x1234 for real?
v) printf("value at the address %d",*(236632));//consider the address 236632 available in
//stack
why does the above printf statement showing error?
That's a type cast, it tells the compiler to treat one type as some other (possibly unrelated) type. As for the result, see point 2 below.
That makes cptr point to the address 2345.
Modern operating systems isolate the processes. The address of one variable in one process is not valid in another process, even if started with the same program. In fact, the second process may have a completely different memory map due to Address Space Layout Randomisation (ASLR).
It's because you try to write to address 0x1234 which might be a valid address on some systems, but not on most, and almost never on a PC running e.g. Windows or Linux.
i)
(char *) means, that you cast the data stored in value to a pointer ptr, which points to a char. Which means, that ptr points to the memory location 2345. In your code snipet ptr is undefined though. I guess there is more in that program.
ii)
The difference is, that you now write to cptr, which is (as you defined) a pointer pointing to a char. There is not much of a difference as in i) except, that you write to a different variable, and that you use a implicit cast, which gets resolved by the compiler. Again, cptr points now to the location 2345 and expects there to be a char
iii)
Yes you can say it is a virtual address. Also segmentation plays some parts in this game, but at your stage you don't need to worry about it at all. The OS will resolve that for you and makes sure, that you only overwrite variables in the memory space dedicated to your program. So if you run a program twice at the same time, and you print a pointer, it is most likely the same value, but they won't point at the same value in memory.
iv)
Didn't see the write instruction at first. You can't just write anywhere into memory, as you could overwrite another program's value.
v)
Similar issue as above. You cannot just dereference any number you want to, you first need to cast it to a pointer, otherwise neither the compiler, your OS nor your CPU will have a clue, to what exactely it is pointing to
Hope I could help you, but I recommend, that you dive again in some books about pointers in C.
i.) Type cast, you cast the integer to a char
ii.) You point to the address of 2345.
iii.) Refer to answer from Joachim Pileborg. ^ ASLR
iv.) You can't directly write into an address without knowing if there's already something in / if it even exists.
v.) Because you're actually using a pointer to print a normal integer out, which should throw the error C2100: illegal indirection.
You may think pointers like numbers on mailboxes. When you set a value to a pointer, e.g cptr = 2345 is like you move in front of mailbox 2345. That's ok, no actual interaction with the memory, hence no crash. When you state something like *cptr, this refers to the actual "content of the mailbox". Setting a value for *cptr is like trying to put something in the mailbox in front of you (memory location). If you don't know who it belongs to (how the application uses that memory), it's probably a bad idea. You could use "malloc" to initialize a pointer / allocate memory, and "free" to cleanup after you finish the job.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is it possible to find out the variable name, the pointer pointing to?
Is it Possible to get the name of array the pointer pointing too?
example:
char name[20];
char *p=name
int door_no;
int *q= & door_no
In the above example we are giving the base address of the array with the array name and pointer q pointing to door_no but what if, I have to know the name of the variable the array pointing too? what is the variable name pointer q is pointing too ? Is it possible I made tries and I came to a conclusion no its not possible but still Iam trying to get the solution. and what you think guys ? Is there any way to make it possible?
Short answer: No.
Long Answer:
In C variable names do not exist after compilation (everything is converted to either memory locations or register locations).
The compiler may potentially assign multiple variables to the same memory/register location if their lifespans of the two objects do not overlap. Thus the concept of variable names at runtime has no meaning (in the context of C)
No, it's not possible. Your pointer holds an address to a space in memory. The variable name is a name you have defined to mean that space in memory. So, you have somthing like this:
name -> mem space
q ------^
There is nothing linking q to name, and they don't go backwards. Both of them will get you to memory space, but you can't map back to them. Also, the program does not know that these happen to map to the same thing! The only reason you know is because you set it up to do so.
It is possible, but only within the scope of the original object.
You gave these examples (I've modified the formatting slightly):
char name[20];
char *p = name;
int door_no;
int *q = &door_no;
You can do comparisons equivalent to your assignments, thus:
if (p == name)
printf("p == name\n");
if (q == &door_no)
printf("q == &door_no\n");
This started as a comment, but then I realized it probably works better as an actual answer.
The short answer to the question as stated is, as others have already pointed out, no, you cannot map from a memory location to a variable name corresponding to that location.
Think about what would happen if it actually was possible to do something like what you want. Here is a thought experiment for you. I'm assuming C, but it should apply equally well in any language that supports pointers to arbitrary memory locations (including memory locations occupied by other variables).
Suppose that you start out with two pointers to an identical memory location:
char p[] = DUMMY;
char *q = &p;
Now, if you were to somehow de-dereference &q, you'd get p. Okay, that kinda-sorta works, in the theoretical sense. Now, add this:
char *r = &q;
Now, you have double indirection. If you try to figure out what names point to the same memory location as the name p, what is the result? If I recall the pointer syntax correct, you get *q and *(*r). How is the compiler going to tell you that, particularly at runtime?
Suppose that p[] is sufficiently large. For an arbitrary number n, replace the *q assignment by:
char *q = &p + n;
What is now the result of similarly de-dereferencing q? What would be the result in case q now points outside the bounds of p[]? (Okay, that latter could conceivably be just q, but then what's the point?)
Or, a practice which was quite common before the wide advent of GUIs. Try this (never mind the actual address).
short *videomemory = 0xB8000;
/* and then, at some later point... */
videomemory += 4;
Then, try to find the address corresponding to the value of videomemory (0xB8004, given the above). What is the result? In principle, the "array" videomemory[] extends indefinitely, even wrapping around (let's ignore memory protection for the moment), and thus anything will map into the memory "occupied" by videomemory[], only given a large enough array index.
It is not possible to get the name of the variables p or q point to if you compile and execute the program traditionally, because one of the things the compiler does is forget the name of the variables, keeping only addresses.
Depending on what you are trying to do, you may execute the program in a non-traditional execution environment where the names are preserved. For instance,
~ $ cat t.c
main(){
char name[20];
char *p=name;
int door_no;
int *q= & door_no;
}
~ $ frama-c -val t.c
[kernel] preprocessing with "gcc -C -E -I. t.c"
...
[value] ====== VALUES COMPUTED ======
[value] Values for function main:
p ∈ {{ &name ;}}
q ∈ {{ &door_no ;}}
__retres ∈ {0; }
I have this function which is called about 1000 times from main(). When i initialize a pointer in this function using malloc(), seg fault occurs, possibly because i did not free() it before leaving the function. Now, I tried free()ing the pointer before returning to main, but its of no use, eventually a seg fault occurs.
The above scenario being one thing, how do i initialize double pointers (**ptr) and pointer to array of pointers (*ptr[])?
Is there a way to copy a string ( which is a char array) into an array of char pointers.
char arr[]; (Lets say there are fifty such arrays)
char *ptr_arr[50]; Now i want point each such char arr[] in *ptr_arr[]
How do i initialize char *ptr_arr[] here?
What are the effects of uninitialized pointers in C?
Does strcpy() append the '\0' on its own or do we have to do it manually? How safe is strcpy() compared to strncpy()? Like wise with strcat() and strncat().
Thanks.
Segfault can be caused by many things. Do you check the pointer after the malloc (if it's NULL)? Step through the lines of the code to see exactly where does it happen (and ask a seperate question with more details and code)
You don't seem to understand the relation of pointers and arrays in C. First, a pointer to array of pointers is defined like type*** or type**[]. In practice, only twice-indirected pointers are useful. Still, you can have something like this, just dereference the pointer enough times and do the actual memory allocation.
This is messy. Should be a separate question.
They most likely crash your program, BUT this is undefined, so you can't be sure. They might have the address of an already used memory "slot", so there might be a bug you don't even notice.
From your question, my advice would be to google "pointers in C" and read some tutorials to get an understanding of what pointers are and how to use them - there's a lot that would need to be repeated in an SO answer to get you up to speed.
The top two hits are here and here.
It's hard to answer your first question without seeing some code -- Segmentation Faults are tricky to track down and seeing the code would be more straightforward.
Double pointers are not more special than single pointers as the concepts behind them are the same. For example...
char * c = malloc(4);
char **c = &c;
I'm not quite sure what c) is asking, but to answer your last question, uninitialized pointers have undefined action in C, ie. you shouldn't rely on any specific result happening.
EDIT: You seem to have added a question since I replied...
strcpy(..) will indeed copy the null terminator of the source string to the destination string.
for part 'a', maybe this helps:
void myfunction(void) {
int * p = (int *) malloc (sizeof(int));
free(p);
}
int main () {
int i;
for (i = 0; i < 1000; i++)
myfunction();
return 0;
}
Here's a nice introduction to pointers from Stanford.
A pointer is a special type of variable which holds the address or location of another variable. Pointers point to these locations by keeping a record of the spot at which they were stored. Pointers to variables are found by recording the address at which a variable is stored. It is always possible to find the address of a piece of storage in C using the special & operator. For instance: if location were a float type variable, it would be easy to find a pointer to it called location_ptr
float location;
float *location_ptr,*address;
location_ptr = &(location);
or
address = &(location);
The declarations of pointers look a little strange at first. The star * symbol which stands in front of the variable name is C's way of declaring that variable to be a pointer. The four lines above make two identical pointers to a floating point variable called location, one of them is called location_ptr and the other is called address. The point is that a pointer is just a place to keep a record of the address of a variable, so they are really the same thing.
A pointer is a bundle of information that has two parts. One part is the address of the beginning of the segment of memory that holds whatever is pointed to. The other part is the type of value that the pointer points to the beginning of. This tells the computer how much of the memory after the beginning to read and how to interpret it. Thus, if the pointer is of a type int, the segment of memory returned will be four bytes long (32 bits) and be interpreted as an integer. In the case of a function, the type is the type of value that the function will return, although the address is the address of the beginning of the function executable.
Also get more tutorial on C/C++ Programming on http://www.jnucode.blogspot.com
You've added an additional question about strcpy/strncpy.
strcpy is actually safer.
It copies a nul terminated string, and it adds the nul terminator to the copy. i.e. you get an exact duplicate of the original string.
strncpy on the other hand has two distinct behaviours:
if the source string is fewer than 'n' characters long, it acts just as strcpy, nul terminating the copy
if the source string is greater than or equal to 'n' characters long, then it simply stops copying when it gets to 'n', and leaves the string unterminated. It is therefore necessary to always nul-terminate the resulting string to be sure it's still valid:
char dest[123];
strncpy(dest, source, 123);
dest[122] = '\0';