Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 6 years ago.
Improve this question
I would like to know why this occurs. I am creating a 5-element array of integers - meaning each element takes 4 Bytes in the memory. Why when I print the address of myArray[-1] I also get a valid address?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int myArray[] = {1, 2, 3, 4, 5};
printf("0x%p\n0x%p\n0x%p\n", &myArray[-1], &myArray[0], &myArray[1]);
return 0;
}
Output:
0x0028FEF8
0x0028FEFC
0x0028FF00
Because undefined behavior is undefined: it may work or not, you are not guaranteed to get a segmentation fault.
The address isn't valid; it doesn't correspond to an object in your program. Attempting to access that memory location results in undefined behavior - it may cause a runtime error. Or not.
On almost any implementation, your array will be materialized in a larger region of storage, so naturally there will be memory cells on either side of that array (unless it starts at address 0, which it won't on almost any implementation you'll actually work on). Since C doesn't enforce any kinds of bounds checking on array accesses, it doesn't immediately throw an exception when you use the -1 subscript. Yes, you get what looks like a reasonable address value, but attempting to use that memory location may or may not result in some kind of mayhem depending on what's stored there (like a frame pointer, for example). The language definition leaves the behavior undefined; it places no requirement on the compiler to do handle the situation in any particular way. The compiler may issue a diagnostic that you're doing something stupid and halt translation. It may compile the code without complaint, and you won't know anything's wrong until you get a runtime error. It may do anything in between.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
int a=10;
char *b ;
b=(char*)&a;
strcpy(b,"xxxxx");
printf("%s",b);
The compilation can pass, but the program exits with an error. Why doesn't this work? What is the mechanism of realization?
It is likely that, in your C implementation, int is four bytes. The C standard defines a char to use one byte. So b = (char *) &a; sets b to point the first byte of the four that make up a. We do not know what lies after those four bytes.
strcpy(b, "xxxxx"); asks strcpy to copy six bytes (the five “x” characters and a terminating null character) to the memory pointed to by b. In the simplest case, this will overwrite two bytes beyond a. This can disrupt your program in a variety of ways—it can corrupt some other data the compiler stored there, it can make your stack frame unusable, it can corrupt a return address, and other things can go wrong.
Additionally, when the compiler translates and optimizes your program, it relies on guarantees made to it by the C standard, such as that the operation strcpy(b, …) will not write outside of the properly defined object pointed to by b, which is a. When you violate those guarantees, the C standard does not define the resulting behavior, and the translations and optimizations made by the compiler may cause your program to go awry in unexpected ways.
int a=10;
char *b ;
b=(char*)&a;
strcpy(b,"xxxxx");
printf("%s",b);
Why doesn't this work?
This doesn't work because strcpy() copy 6 characters (5 times 'x' and one nul terminator) to the address pointed by b and there is not enough room for that, at least if the compiler you used store int type into 32bits (4 bytes).
You didn't showed the full code, but assuming a is a local variable, it is allocated on the stack. You overflow the space allocated for variable a and this means you overwrite something on the stack. That data on the stack is essential for program continuation and being overwritten it crashes the system.
"at will"? No they are actually sentient!
If code does not behave as you expect it is because you have a semantic error - that is code that is syntactically valid (i.e. it compiles) but does not mean what you think it does when executed according to the rules of the language.
Moreover as systems level language C does not protect you from doing invalid things to the execution environment - i.e. runtime errors, and such errors generally have undefined behaviour.
In this case:
b=(char*)&a;
strcpy(b,"xxxxx");
b points to an object of int size. On Windows or any 32 bit system, that will normally be 4 bytes. You then copy 6 bytes to it, overrunning its space. The effect of this is undefined, but it is likely that it will corrupt some adjacent variable in memory or the function return address.
If b were corrupted by the strcpy() error, trying to print the string at b would cause a run-time error is b were no longer a valid address.
If the return address were corrupted, the program would fail when you return from the calling function.
In either case the precise behaviour is not defined, and may not be trapped; it depends on when gets corrupted, what value the corrupted data takes, and how and when that corrupted data is used.
You will be able to observe the effects on the variables and/or call stack by running and stepping this code in a debugger.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am new to C; I have more background knowledge with Java.
I want to try searching for value in memory using pointer
#include <stdio.h>
void main(){
int value = 10;
find(value);
}
void find(int value){ // will change this to return array of long or int depending on which is better
int* intPointer;
for(int i = 40000; i < 40400 ; i+= 32){ /* not sure if i do it like this or another way,
* the starting value, ending value and condition
* is just for testing purpose */
intPointer = (int*)i;
if(*intPointer == value){
printf("found value"); //will actually be storing it to an array instead
}
}
}
The find method gives me a segmentation fault most likely because the address does not store int value. Is there a way I can find out what type data is stored in the memory address.
Is there a better way of achieving a similar task? Please explain and show. The actual program will not have int value = ?? instead only the find method will be used to get a array of addresses which contains this value.
Also what is the best type to store addresses int or long?
A couple things to know right off the bat:
Memory is not always guaranteed to be physically contiguous (even if the memory model appears to be as such).
Knowing what a segfault is would be helpful, as well as what segmented memory and memory protection are in general
The find method gives me a segmentation fault most likely because the address does not store int value
From what I can tell you are trying to loop through memory addresses and find a specific value. Technically it's possible, but practically there's no reason to do it except a few rare cases.
Unfortunately (for your purposes) your operating system of choice handles memory rather intelligently; instead of just placing everything it is given in a linear order, it divides (or segments) memory into their own address spaces to keep memory of process A from interfering with memory of process B, and so forth. To keep track of which processes are where in memory, a mapping mechanism is used.
You tried to access memory outside of your program's assigned segment. To be able to do what it seems you want to do, you're going to need to find a way to get the memory map from the OS.
is there a way I can find out what type data is stored in the memory address
No, at least not in the way you want. A couple SO answers address this.
There is no way to do what you trying in a generic portable way. The code generates undefined behavior as you are accessing memory not allocated to you.
On simple embedded systems it may be possible. To start with, it will require that you have full insight in the systems memory layout and how the compiler works. For instance, you must know whether int is always 4 byte aligned in memory, start/end address of RAM. If an MMU is present and active, you also need to know how it works.
is there a way I can find out what type data is stored in the memory address.
No
You are faking a pointer with a temporary var inside the loop.
The correct way to search for a value would be to have two arguments: the value to search for, and a collection (array, for example) containing some values to be searched.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Is a memcpy of a chunk of one array to another in C guilty of Vaxocentrism?
Example:
double A[10];
double B[10];
// ... do stuff ...
// copy elements 3 to 7 in A to elements 2 to 6 in B
memcpy(B+2, A+3, 5*sizeof(double)
As a related question, is casting from an array to a pointer Vaxocentrist?
char A[10];
char* B = (char*)A;
B[0]=2;
A[1]=3;
B[2]=5;
I certainly appreciate the idea of writing code that works under different machine architectures and different compilers, but if I applied type safety to the extreme it would cripple many of C's useful features! How much / little can I assume about how the compiler implements arrays/pointers/etc.?
No. The model on which memcpy works is defined in the abstract machine specified by the C language standard and has nothing to do with any particular physical machine it might be running on. In particular, all objects in C have a representation which is defined as an overlaid array of type unsigned char[sizeof object], and memcpy works on this representation.
Likewise, the 'decay' of arrays to pointers via cast or implicit conversion is completely defined on the abstract machine and has nothing to do with physical machines.
Further, none of the points 1-14 in the linked article have anything to do with the code you're asking about.
In C code, memcpy() can be a useful optimization in a couple of cases. First, if the array of memory is very small then the copy operation can often be inlined directly by the compiler instead of calling a function. This can be a big win in a tight loop that runs a lot. Second, in the case where the array is very large and the hardware supports a faster mode of memory access for certain aligned memory cases then that faster code can be used for the vast majority of the memory. You honestly do not want to know the scary details of alignment and copy operations for different hardware, better to just put that stuff in memcpy() and let everyone use it.
For your first example you're using the + operator incorrectly. You want to deference the element its pointing to. This is safe because both arrays are of size 10, and when allocating memory for arrays all the addresses are sequential with respect to element 0. Also you're copying doesn't go outside of the bounds of the declared array that you're copying to, B.
memcpy(&B[2], &A[3], 5*sizeof(double));
On your related point, you're making the same mistake, you'd want to do the following:
char A[10];
char* B = &A[0];
B[0]=2;
A[1]=3;
B[2]=5;
This question already has answers here:
How dangerous is it to access an array out of bounds?
(12 answers)
Closed 8 years ago.
In c program we can initialize an array like int array[10]. So it can store 10 integer value.But when I give input using loop it takes input more than 10 and doesn't show any error.
actually what is happening??
#include<stdio.H>
main()
{
int array[10],i;
for(i=0;i<=11;i++)
scanf("%d",&array[i]);
for(i=0;i<10;i++)
printf("%d",array[i]);
}
Because C doesn't do any array bounds checking. You as a programmer are responsible for making sure that you don't index out of bounds.
Depending on the used compiler and the system the code is running on, you might read random data from memory or get a SIGSEGV eventually when reading/writing out of bounds.
The C compiler and the runtime are not required to perform any array bounds checking.
What you describe is an example of a whole class of programming errors that result in undefined behavior. From Wikipedia:
In computer programming, undefined behavior refers to computer code whose behavior is specified to be arbitrary.
What this means is that the program is allowed to misbehave (or not) in any way it pleases.
In practice, any of the following are reasonably likely to happen when you write past the end of an array:
The program crashes, either immediately or at a later point.
Other, unrelated, data gets overwritten. This could result in arbitrary misbehaviour and/or in serious security vulnerabilities.
Internal data structures that are used to keep track of allocated memory get corrupted by the out-of-bounds write.
The program works exactly as if more memory had been allocated in the first place (memory is often allocated in block, and by luck there might happen to be some spare capacity after the end of the array).
(This is not an exhaustive list.)
There exist tools, such as Valgrid, that can help discover and diagnose this type of errors.
The C-language standard does not dictate how variables should be allocated in memory.
So the theoretical answer is that you are performing an unsafe memory access operation, which will lead to undefined behavior (anything could happen).
Technically, however, all compilers allocate local variables in the stack and global variables in the data-section, so the practical answer is:
In the case of a local array, you will either override some other local variable or perform an illegal memory access operation.
In the case of a global array, you will either override some other global variable or perform an illegal memory access operation.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Could anyone clarify this?
char str[1];
strcpy(str, "HHHHHHHHHHHH");
Here I declared a char array with size one, but the program doesn't crash untill I enter more than 12 characters and I only have an array size one. Why?
This code has undefined behaviour, since it writes more than one element into str. It could do anything. It is your responsibility to ensure that you only write into memory that you own.
This is undefined behaviour. In practice, you overwrite memory contents of something. In this case, that array goes to stack, if it is a local variable. It is likely that you have a CPU architecture where stack grows down, so you start overwriting things like other local variables, saved register values and return addresses of function calls.
You probably first overwrote something which had no immediate effect, or you did not notice the effect. This might be a local variable which wasn't initialized yet, or a local variable or saved register value which was not actually used after you overwrote it.
Then when you increased length of overflow, you probably corrupted function return address, and then crash actually happened when you returned from the function. If you had any other memory addresses, that is pointers, crash could also be because you tried to access the value pointed by corrupted pointer.
Finally, if you would increase the overflow size enough, the string copying would eventually directly write outside allowed area and cause immediate crash (assuming CPU and OS which have such memory protection, and not some ancient or embedded system). But this probably was not the reason here, as you wrote only 14 bytes before crash.
But note that above is kinda pointless from point of view of C language, undefined behaviour, which often changes if you chnage anything in the program, compiler options or input data. This can make memory corruption bugs hard to find, as adding debug stuff often makes the problem "disappear" (changes or hides the symptoms).