Read and write to a memory location - c

After doing lot of research in Google, I found this program:
#include <stdio.h>
int main()
{
int val;
char *a = (char*) 0x1000;
*a = 20;
val = *a;
printf("%d", val);
}
But it is throwing a run time error, at *a = 20.
So how can I write and read a specific memory location?

You are doing it except on your system you cannot write to this memory causing a segmentation fault.
A segmentation fault (often shortened to segfault), bus error or access violation is generally an attempt to access memory that the CPU cannot physically address. It occurs when the hardware notifies an operating system about a memory access violation. The OS kernel then sends a signal to the process which caused the exception. By default, the process receiving the signal dumps core and terminates. The default signal handler can also be overridden to customize how the signal is handled.
If you are interested in knowing more look up MMU on wikipedia.
Here is how to legally request memory from the heap. The malloc() function takes a number of bytes to allocate as a parameter. Please note that every malloc() should be matched by a free() call to that same memory after you are done using it. The free() call should normally be in the same function as where you called malloc().
#include <stdio.h>
int main()
{
int val;
char *a;
a = (char*)malloc(sizeof(char) * 1);
*a = 20;
val = (int)*a;
printf("%d", val);
free(a);
return 0;
}
You can also allocate memory on the stack in a very simple way like so:
#include <stdio.h>
int main()
{
int val;
char *a;
char b;
a = &b;
*a = 20;
val = (int)*a;
printf("%d", val);
return 0;
}

This is throwing a segment violation (SEGFAULT), as it should, as you don't know what is put in that address. Most likely, that is kernel space, and the hosting environment doesn't want you willy-nilly writing to another application's memory. You should only ever write to memory that you KNOW your program has access to, or you will have inexplicable crashes at runtime.

If you are running your code in user space(which you are), then all the addresses you get are virtual addresses and not physical addresses. You cannot just assume and write to any virtual address.
In fact with virtual memory model you cannot just assume any address to be a valid address.It is up to the memory manager to return valid addresses to the compiler implementation which the handles it to your user program and not the other way round.
In order that your program be able to write to an address:
It should be a valid virtual address
It should accessible to the address space of your program

You can't just write at any random address. You can only modify the contents of memory where your program can write.
If you need to modify contents of some variable, thats why pointers are for.
char a = 'x';
char* ptr = &a; // stored at some 0x....
*ptr = 'b'; // you just wrote at 0x....

Issue of permission, the OS will protect memory space from random access.
You didn't specify the exact error, but my guess is you are getting a "segmentation fault" which would clearly indicate a memory access violation.

You can write to a specific memory location.
But only when you have the rights to write to that location.
What you are getting, is the operating system forbidding you to write to 0x1000.

That is the correct way to write data to memory location 0x1000. But in this day and age of virtual memory, you almost never know the actual memory location you want to write to in advance, so this type of thing is never used.
If you can tell us the actual problem you're trying to solve with this, maybe we can help.

You cannot randomly pick a memory location and write to. The memory location must be allocated to you and must be writable.
Generally speaking, you can get the reference/address of a variable with & and write data on it. Or you can use malloc() to ask for space on heap to write data to.
This answer only covers how to write and read data on memory. But I don't cover how to do it in the correct way, so that the program functions normally. Other answer probably covers this better than mine.

First you need to be sure about memory location where you want to write into.
Then, check if you have enough permission to write or not.

Related

Under what circumstances does a segmentation fault occur? [duplicate]

What is a segmentation fault? Is it different in C and C++? How are segmentation faults and dangling pointers related?
Segmentation fault is a specific kind of error caused by accessing memory that “does not belong to you.” It’s a helper mechanism that keeps you from corrupting the memory and introducing hard-to-debug memory bugs. Whenever you get a segfault you know you are doing something wrong with memory – accessing a variable that has already been freed, writing to a read-only portion of the memory, etc. Segmentation fault is essentially the same in most languages that let you mess with memory management, there is no principal difference between segfaults in C and C++.
There are many ways to get a segfault, at least in the lower-level languages such as C(++). A common way to get a segfault is to dereference a null pointer:
int *p = NULL;
*p = 1;
Another segfault happens when you try to write to a portion of memory that was marked as read-only:
char *str = "Foo"; // Compiler marks the constant string as read-only
*str = 'b'; // Which means this is illegal and results in a segfault
Dangling pointer points to a thing that does not exist anymore, like here:
char *p = NULL;
{
char c;
p = &c;
}
// Now p is dangling
The pointer p dangles because it points to the character variable c that ceased to exist after the block ended. And when you try to dereference dangling pointer (like *p='A'), you would probably get a segfault.
It would be worth noting that segmentation fault isn't caused by directly accessing another process memory (this is what I'm hearing sometimes), as it is simply not possible. With virtual memory every process has its own virtual address space and there is no way to access another one using any value of pointer. Exception to this can be shared libraries which are same physical address space mapped to (possibly) different virtual addresses and kernel memory which is even mapped in the same way in every process (to avoid TLB flushing on syscall, I think). And things like shmat ;) - these are what I count as 'indirect' access. One can, however, check that they are usually located long way from process code and we are usually able to access them (this is why they are there, nevertheless accessing them in a improper way will produce segmentation fault).
Still, segmentation fault can occur in case of accessing our own (process) memory in improper way (for instance trying to write to non-writable space). But the most common reason for it is the access to the part of the virtual address space that is not mapped to physical one at all.
And all of this with respect to virtual memory systems.
A segmentation fault is caused by a request for a page that the process does not have listed in its descriptor table, or an invalid request for a page that it does have listed (e.g. a write request on a read-only page).
A dangling pointer is a pointer that may or may not point to a valid page, but does point to an "unexpected" segment of memory.
To be honest, as other posters have mentioned, Wikipedia has a very good article on this so have a look there. This type of error is very common and often called other things such as Access Violation or General Protection Fault.
They are no different in C, C++ or any other language that allows pointers. These kinds of errors are usually caused by pointers that are
Used before being properly initialised
Used after the memory they point to has been realloced or deleted.
Used in an indexed array where the index is outside of the array bounds. This is generally only when you're doing pointer math on traditional arrays or c-strings, not STL / Boost based collections (in C++.)
According to Wikipedia:
A segmentation fault occurs when a
program attempts to access a memory
location that it is not allowed to
access, or attempts to access a memory
location in a way that is not allowed
(for example, attempting to write to a
read-only location, or to overwrite
part of the operating system).
Segmentation fault is also caused by hardware failures, in this case the RAM memories. This is the less common cause, but if you don't find an error in your code, maybe a memtest could help you.
The solution in this case, change the RAM.
edit:
Here there is a reference: Segmentation fault by hardware
Wikipedia's Segmentation_fault page has a very nice description about it, just pointing out the causes and reasons. Have a look into the wiki for a detailed description.
In computing, a segmentation fault (often shortened to segfault) or access violation is a fault raised by hardware with memory protection, notifying an operating system (OS) about a memory access violation.
The following are some typical causes of a segmentation fault:
Dereferencing NULL pointers – this is special-cased by memory management hardware
Attempting to access a nonexistent memory address (outside process's address space)
Attempting to access memory the program does not have rights to (such as kernel structures in process context)
Attempting to write read-only memory (such as code segment)
These in turn are often caused by programming errors that result in invalid memory access:
Dereferencing or assigning to an uninitialized pointer (wild pointer, which points to a random memory address)
Dereferencing or assigning to a freed pointer (dangling pointer, which points to memory that has been freed/deallocated/deleted)
A buffer overflow.
A stack overflow.
Attempting to execute a program that does not compile correctly. (Some compilers will output an executable file despite the presence of compile-time errors.)
Segmentation fault occurs when a process (running instance of a program) is trying to access read-only memory address or memory range which is being used by other process or access the non-existent (invalid) memory address.
Dangling Reference (pointer) problem means that trying to access an object or variable whose contents have already been deleted from memory, e.g:
int *arr = new int[20];
delete arr;
cout<<arr[1]; //dangling problem occurs here
In simple words: segmentation fault is the operating system sending a signal to the program
saying that it has detected an illegal memory access and is prematurely terminating the program to prevent
memory from being corrupted.
There are several good explanations of "Segmentation fault" in the answers, but since with segmentation fault often there's a dump of the memory content, I wanted to share where the relationship between the "core dumped" part in Segmentation fault (core dumped) and memory comes from:
From about 1955 to 1975 - before semiconductor memory - the dominant technology in computer memory used tiny magnetic doughnuts strung on copper wires. The doughnuts were known as "ferrite cores" and main memory thus known as "core memory" or "core".
Taken from here.
"Segmentation fault" means that you tried to access memory that you do not have access to.
The first problem is with your arguments of main. The main function should be int main(int argc, char *argv[]), and you should check that argc is at least 2 before accessing argv[1].
Also, since you're passing in a float to printf (which, by the way, gets converted to a double when passing to printf), you should use the %f format specifier. The %s format specifier is for strings ('\0'-terminated character arrays).
Simple meaning of Segmentation fault is that you are trying to access some memory which doesn't belong to you. Segmentation fault occurs when we attempt to read and/or write tasks in a read only memory location or try to freed memory. In other words, we can explain this as some sort of memory corruption.
Below I mention common mistakes done by programmers that lead to Segmentation fault.
Use scanf() in wrong way(forgot to put &).
int num;
scanf("%d", num);// must use &num instead of num
Use pointers in wrong way.
int *num;
printf("%d",*num); //*num should be correct as num only
//Unless You can use *num but you have to point this pointer to valid memory address before accessing it.
Modifying a string literal(pointer try to write or modify a read only memory.)
char *str;
//Stored in read only part of data segment
str = "GfG";
//Problem: trying to modify read only memory
*(str+1) = 'n';
Try to reach through an address which is already freed.
// allocating memory to num
int* num = malloc(8);
*num = 100;
// de-allocated the space allocated to num
free(num);
// num is already freed there for it cause segmentation fault
*num = 110;
Stack Overflow -: Running out of memory on the stack
Accessing an array out of bounds'
Use wrong format specifiers when using printf() and scanf()'
Consider the following snippets of Code,
SNIPPET 1
int *number = NULL;
*number = 1;
SNIPPET 2
int *number = malloc(sizeof(int));
*number = 1;
I'd assume you know the meaning of the functions: malloc() and sizeof() if you are asking this question.
Now that that is settled,
SNIPPET 1 would throw a Segmentation Fault Error.
while SNIPPET 2 would not.
Here's why.
The first line of snippet one is creating a variable(*number) to store the address of some other variable but in this case it is initialized to NULL.
on the other hand,
The second line of snippet two is creating the same variable(*number) to store the address of some other and in this case it is given a memory address(because malloc() is a function in C/C++ that returns a memory address of the computer)
The point is you cannot put water inside a bowl that has not been bought OR a bowl that has been bought but has not been authorized for use by you.
When you try to do that, the computer is alerted and it throws a SegFault error.
You should only face this errors with languages that are close to low-level like C/C++. There is an abstraction in other High Level Languages that ensure you do not make this error.
It is also paramount to understand that Segmentation Fault is not language-specific.
There are enough definitions of segmentation fault, I would like to quote few examples which I came across while programming, which might seem like silly mistakes, but will waste a lot of time.
You can get a segmentation fault in below case while argument type mismatch in printf:
#include <stdio.h>
int main(){
int a = 5;
printf("%s",a);
return 0;
}
output : Segmentation Fault (SIGSEGV)
When you forgot to allocate memory to a pointer, but try to use it.
#include <stdio.h>
typedef struct{
int a;
} myStruct;
int main(){
myStruct *s;
/* few lines of code */
s->a = 5;
return 0;
}
output : Segmentation Fault (SIGSEGV)
In computing, a segmentation fault or access violation is a fault, or failure condition, raised by hardware with memory protection,
notifying an operating system the software has attempted to access a
restricted area of memory. -WIKIPEDIA
You might be accessing the computer memory with the wrong data type. Your case might be like the code below:
#include <stdio.h>
int main(int argc, char *argv[]) {
char A = 'asd';
puts(A);
return 0;
}
'asd' -> is a character chain rather than a single character char data type. So, storing it as a char causes the segmentation fault. Stocking some data at the wrong position.
Storing this string or character chain as a single char is trying to fit a square peg in a round hole.
Terminated due to signal: SEGMENTATION FAULT (11)
Segm. Fault is the same as trying to breath in under water, your lungs were not made for that. Reserving memory for an integer and then trying to operate it as another data type won't work at all.
Segmentation fault occurs when a process (running instance of a program) is trying to access a read-only memory address or memory range which is being used by another process or access the non-existent memory address.
seg fault,when type gets mismatched
A segmentation fault or access violation occurs when a program attempts to access a memory location that is not exist, or attempts to access a memory location in a way that is not allowed.
/* "Array out of bounds" error
valid indices for array foo
are 0, 1, ... 999 */
int foo[1000];
for (int i = 0; i <= 1000 ; i++)
foo[i] = i;
Here i[1000] not exist, so segfault occurs.
Causes of segmentation fault:
it arise primarily due to errors in use of pointers for virtual memory addressing, particularly illegal access.
De-referencing NULL pointers – this is special-cased by memory management hardware.
Attempting to access a nonexistent memory address (outside process’s address space).
Attempting to access memory the program does not have rights to (such as kernel structures in process context).
Attempting to write read-only memory (such as code segment).

Dereferencing pointer to arbitrary address gives Segmentation fault

I have written a simple C code for pointers. As per my understanding, Pointer is a variable which holds the address of another variable.
Eg :
int x = 25; // address - 1024
int *ptr = &x;
printf("%d", *ptr); // *ptr will give value at address of x i.e, 25 at 1024 address.
However when I try below code I'm getting segmentation fault
#include "stdio.h"
int main()
{
int *ptr = 25;
printf("%d", *ptr);
return 0;
}
What's wrong in this? Why can't a pointer variable return the value at address 25? Shouldn't I be able to read the bytes at that address?
Unless you're running on an embedded system with specific known memory locations, you can't assign an arbitrary value to a pointer an expect to be able to dereference it successfully.
Section 6.5.3.2p4 of the C standard states the following regarding the indirection operator *:
The unary
* operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an
object, the result is an lvalue designating the object. If
the operand has type "pointer to type", the result has
type "type". If an invalid value has been assigned to
the pointer, the behavior of the unary
* operator is undefined.
As mentioned in the passage above, the C standard only allows for pointers to point to known objects or to dynamically allocated memory (or NULL), not arbitrary memory locations. Some implementations may allow that in specific situations, but not in general.
Although the behavior of your program is undefined according to the C standard, your code is actually correct in the sense that it is doing exactly what you intend. It is attempting to read from memory address 25 and print the value at that address.
However, in most modern operating systems, such as Windows and Linux, programs use virtual memory and not physical memory. Therefore, you are most likely attempting to access a virtual memory address that is not mapped to a physical memory address. Accessing an unmapped memory location is illegal and causes a segmentation fault.
Since the memory address 0 (which is written in C as NULL) is normally reserved to specify an invalid memory address, most modern operating systems never map the first few kilobytes of virtual memory addresses to physical memory. That way, a segmentation fault will occur when an invalid NULL pointer is dereferenced (which is good, because it makes it easier to detect bugs).
For this reason, you can be reasonably certain that also the address 25 (which is very close to address 0) is never mapped to physical memory and will therefore cause a segmentation fault if you attempt to access that address.
However, most other addresses in your program's virtual memory address space will most likely have the same problem. Since the operating system tries to save physical memory if possible, it will not map more virtual memory address space to physical memory than necessary. Therefore, trying to guess valid memory addresses will fail, most of the time.
If you want to explore the virtual address space of your process to find memory addresses that you can read without a segmentation fault occuring, you can use the appropriate API supplied by your operating system. On Windows, you can use the function VirtualQuery. On Linux, you can read the pseudo-filesystem /proc/self/maps. The ISO C standard itself does not provide any way of determining the layout of your virtual memory address space, as this is operating system specific.
If you want to explore the virtual memory address layout of other running processes, then you can use the VirtualQueryEx function on Windows and read /proc/[pid]/maps on Linux. However, since other processes have a separate virtual memory address space, you can't access their memory directly, but must use the ReadProcessMemory and WriteProcessMemory functions on Windows and use /proc/[pid]/mem on Linux.
Disclaimer: Of course, I don't recommend messing around with the memory of other processes, unless you know exactly what you are doing.
However, as a programmer, you normally don't want to explore the virtual memory address space. Instead, you normally work with memory that has been assigned to your program by the operating system. If you want the operating system to give you some memory to play around with, which you are allowed to read from and write to at will (i.e. without segmentation faults), then you can just declare a large array of chars (bytes) as a global variable, for example char buffer[1024];. Be careful with declaring larger arrays as local variables, as this may cause a stack overflow. Alternatively, you can ask the operating system for dynamically allocated memory, for example using the malloc function.
You should consider all warnings that the compiler issues.
This statement
int *ptr = 25;
is incorrect. You are trying to assign an integer to a pointer as an address of memory. Thus in this statement
printf("%d", *ptr);
there is an attempt to access memory at address 25 that does not belong to your program.
What you mean is the following
#include "stdio.h"
int main( void )
{
int x = 25;
int *ptr = &x;
printf("%d", *ptr);
return 0;
}
Or
#include "stdio.h"
#include <stdlib.h>
int main( void )
{
int *ptr = malloc( sizeof( int ) );
*ptr = 25;
printf("%d", *ptr);
free( ptr );
return 0;
}

Why does setting a value at an arbitrary memory location not work?

I have this code:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
int main (int argc, char** argv) {
*(volatile uint8_t*)0x12345678u = 1;
int var = *(volatile uint8_t*)0x12345678;
printf("%i", var);
printf("%i", &var);
return (EXIT_SUCCESS);
}
I want to see a 1 and the address of that int, which i specified previously. But when compiled by gcc in bash, only "command terminated" without any error will be shown. Does anyone know why so?
PS: I am newbie to C, so just experimenting.
What you are doing:
*(volatile uint8_t*)0x12345678u = 1;
int var = *(volatile uint8_t*)0x12345678;
is totally wrong.
You have no guarantee whatsoever that an arbitrary address like 0x12345678 will be accessible, not to mention writable by your program. In other words, you cannot set a value to an arbitrary address and expect it to work. It's undefined behavior to say the least, and will most likely crash your program due to the operating system stopping you from touching memory you don't own.
The "command terminated" that you get when trying to run your program happens exactly because the operating system is preventing your program from accessing a memory location it is not allowed to access. Your program gets killed before it can do anything.
If you are on Linux, you can use the mmap function to request a memory page at an (almost) arbitrary address before accessing it (see man mmap). Here's an example program which achieves what you want:
#include <sys/mman.h>
#include <stdio.h>
#define WANTED_ADDRESS (void *)0x12345000
#define WANTED_OFFSET 0x678 // 0x12345000 + 0x678 = 0x12345678
int main(void) {
// Request a memory page starting at 0x12345000 of 0x1000 (4096) bytes.
unsigned char *mem = mmap(WANTED_ADDRESS, 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// Check if the OS correctly granted your program the requested page.
if (mem != WANTED_ADDRESS) {
perror("mmap failed");
return 1;
}
// Get a pointer inside that page.
int *ptr = (int *)(mem + WANTED_OFFSET); // 0x12345678
// Write to it.
*ptr = 123;
// Inspect the results.
printf("Value : %d\n", *ptr);
printf("Address: %p\n", ptr);
return 0;
}
The operating system and loader do not automatically make every possible address available to your program. The virtual address space of your process is constructed on demand by various operations of the program loader and of services inside the process. Although every address “exists” in the sense of being a potential address of memory, what happens when a process attempts to access an address is controlled by special data structures in the system. Those data structures control whether a process can read, write, or execute various portions of memory, whether the virtual addresses are currently mapped to physical memory, and whether the virtual addresses are not currently mapped to memory but will be provide with physical memory when needed. Initially, much of a process’ address space is marked not in use (or at least implicitly marked, in that none of the explicit records for the address space apply to it).
In the executions of your program you have attempted so far, the address 0x12345678 has not been mapped and marked available to your process, so, when your process attempted to use it, the system detected a fault and terminated your process.
(Some systems randomize the layout of the address space when a program is being loaded, to make it harder for an attacker to exploit bugs in a program. Because of this, it is possible that 0x12345678 will be accessible in some executions of your program and not others.)
The quote from C11 standard 6.5.3.2p4:
4 The unary * operator denotes indirection. [...] If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.
You use * operator on (volatile uint8_t*)0x12345678u pointer. Is this a valid pointer? Is it invalid pointer? What is an "invalid value" of a pointer?
There is no check that allows to find out which particilar pointer values are valid, which aren't. It is not implemented in C language. A random pointer may just happen to be a valid pointer. But most, most probably it is an invalid pointer. In which case - the behavior is undefined.
Dereferencing an invalid pointer is undefined behavior. But - outside of C scope and into operating system - on *unix systems trying to access memory that you are not allowed to, should raise a signal SIGSEGV on your program and terminate your program. Most probably this is what happens. Your program is not allowed to access memory location that is behind 0x12345678 value, the operating system specifically protects against that.
Also note, that systems use ASLR, so that pointer values within your program are indeed in some degree random. There are not linear, ie. *(char*)0x01 will not access the first byte in your ram. Operating system (or more exact, the underlying hardware as configured by the operating system) translates pointer values in your program to physical location in ram using what is called virtual memory. The same pointer values may just happen to be valid on the second run of your program. But most probably, because pointers can have so many values, most probably it isn't a valid pointer. Your operating system kills your program, as it detects an invalid memory access.

malloc function on linux

I'm learning Linux C programming recently,and there is a question have puzzled me long time.The question is that when we use malloc to allocate some memory,we can use the addresses that over the size we required,but when we access a large address than we required,the system may kill our process.just like the following codes:
int *p = malloc(10*sizeof(int));
*(p + 10) = 1;
when we use this clause,the system may not kill our process,but when we use:
*(p +10000) = 1;
the system may kill our process.
So why does the system do it in this way?
Actually, you can access memory you didn't allocate.
It's not C that (sometimes) prevents you from doing so (it's designed after the philosophy that the user is always right), it's the operating system using special MMU (memory management unit) hardware.
This hardware cannot (for performance and cost reasons) secure any arbitrary address, but only ranges of memory (pages). Thus illegal (from a programmer's standpoint) accesses are sometimes possible (if they are on the same memory page where you have legally allocated memory), other illegal accesses (outside pages with legal addresses) are prevented by the MMU that issues a page fault (segmentation violation).
This obviously doesn't mean you are allowed to access unallocated memory, it just explains why you sometimes get by with it.
Of course all this is only true for platforms that actually have a MMU. There are still a lot around that haven't, so better learn your lessons ;).
Obviously, you can only access memory you allocated upfront.
So what you're doing basically is:
int *p = malloc(10 * sizeof(int));
Here, you allocate memory for 10 ints.
*(p + 10) = 1;
This can be rewritten as (by removing pointer arithmetic):
p[10] = 1;
Now, you can clearly see that there's no memory for the 10th item. So in theory, your code should crash here already.
However, often, the OS decides to allocate a little more memory or you've allocated a block of memory next to p (in which case the OS won't intervene, even though your code doesn't work the way you want it to).
Let me give you an example:
char foo[4] = "foo";
char bar[4] = "bar";
Now (in theory, obviously it depends on what your compiler does) if you access the 5th char of foo, it actually maps to the first char of bar:
foo[5] = "c";
printf("%s %s\n", foo, bar); /* == foo car */
As I said, this depends on your compiler and I only give you this example because it might help you understand how the OS allocates memory.
One more thing:
The NULL pointer ((void *)0) is "protected" and the OS guarantees that it fails when you try to access the contents of that address.
if you dynamically allocate memory, you are allocating it on the heap. You do this by assigning a pointer the beginning of your memory block. So you can add an offset to this pointer and access a specific memory location. If this offset is large enough your pointer could end up pointing outside of the heap, or outside of your data section, or to a protected memory location. This will cause a segmentation fault - you may be accessing a memory location which is used for something else.
Your question is unclear, but I think you're asking why you "can" access an element outside of what you allocated. The answer is that you really can't. There's no telling what you'll be stepping on when you do that -- perhaps another variable, maybe even your code. For very large offsets, you'll definitely end up outside of the system memory that you "own", and will have your process killed.
It appears that you have no idea what you're doing with malloc(). Go back and read about it again.

Why do I get a segmentation fault if I print the contents of this memory location

Suppose I do the following
int *p = 1;
printf("%d", *p);
I get a segfault. Now, as I understand it, this memory location 1 is in the address space of my program. Why should there be a problem in reading this memory location ?
Your pointer doesn't point to anything valid. All you do is assign the value 1 to a pointer-to-int, but 1 isn't a valid memory location.
The only valid way to obtain an pointer value is either take the address-of a variable or call an allocation function:
int a;
int * p1 = &a; // OK
int * p2 = malloc(sizeof(int)); // also OK
*p1 = 2;
*p2 = 3;
As for "why there should be a problem": As far as the language is concerned, if you dereference an invalid pointer, you have undefined behaviour, so anything can happen -- this is really the only sensible way to specify the language if you don't want to introduce any arbitrary restrictions, and C is all about being easy-to-implement.
Practically, modern operating systems will usually have a clever virtual memory manager that needs to request memory when and as needed, and if the memory at address 1 isn't on a committed page yet, you'll actually get an error from the OS. If you try a pointer value near some actual address, you might not get an error (until you overstep the page boundary, perhaps).
To answer this properly will really depend upon a number of factors. However, it is quite likely that the address 0x00000001 (page 0) is not mapped and/or read protected.
Typically, addresses in the page 0 range are disallowed from a user application for one reason or another. Even in kernel space (depending upon the processor), addresses in page 0 are often protected and require that the page be both mapped and access enabled.
EDIT:
Another possible reason is that it could be segfaulting is that integer access is not aligned.
Your operating system won't let you access memory locations that don't belong to your program. It would work on kernel mode though...
No, address 1 is not in the address space of your program. You are trying to access a segment you do not own and receive segmentation fault.
You're trying to print 1, not the memory location. 1 isn't a valid memory location. To print the actual memory location do:
printf("%p", p);
Note the %p as icktoofay pointed out.

Resources