definition array of pointers in C [duplicate] - c

This question already has answers here:
Array index out of bound behavior
(10 answers)
Closed 7 years ago.
I want ask about define array of pointers in C.
In following code, I define two pointers to char and then I assign each pointer to return from strtok function.
#include<stdio.h>
#include<string.h>
main()
{
char *s[2], string[]="hehe hihi keke kaka huhu hixhix",delimit[]=" ";
int i=0;
s[i]=strtok(string,delimit);
while( s[i]!=NULL )
{
printf("i=%d -> %s \n",i,s[i]);
++i;
s[i]=strtok(NULL,delimit);
}
}
This is output:
i=0 -> hehe
i=1 -> hihi
i=2 -> keke
i=3 -> kaka
i=4 -> huhu
i=5 -> hixhix
So, I just define two pointers but the code run with no error when i is greater then 1.
Why it work well even when I just define less number of pointers than necessary pointers (eg: 6 or greater) ?
thanks for reading!

Sometimes, it is the case that when you are out of the array area you are in fact changing some unhappy neighbor variable, or some return address.
(In your example you are probably destroying "string" after used.)
In this situation "working well" is much worst then a segmentation fault.
The error, the variable changed, will come to you later, with some unpredictable random behavior always in the worst moment, ( similar situations, were detected in some very big disasters )

Using an invalid index of an array will lead to Undefined Behavior which means that anything can happen. It needn't necessarily "work" as expected or not, or make the program crash or format your hard disk. Anything can happen.

Related

Accessing variable after an array by trying to access a position greater than its dimension in C [duplicate]

This question already has answers here:
How dangerous is it to access an array out of bounds?
(12 answers)
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 3 years ago.
Since in this example I'm able to read value of integer2 thanks to pointer arithmetic:
#include <stdio.h>
int main() {
int integer1 = 1;
int integer2 = 2;
int *p = &integer1;
p++;
printf("%d\n", *p);
}
with output:
$ ./test
2
I was wondering why in this example:
#include <stdio.h>
int main()
{
int array[2] = {0, 1};
int variable = 0;
for(int i = 0; i < 3; i++) {
printf("%d\n", array[i]);
}
}
then I'm not able to read the value of variable trying to point the next integer but that's what I get:
0
1
336859392
I tried printing the values of &array[0] &array[1] and &variable and this is what I got:
161695488
161695492
161695480
Not only the address of variable is less than the one of the first elements of the array, but it's not even the previous one.
Why in the first example variables address are contiguous and in the second one not?
There is probably something I don't understand on how variables and buffers are allocated in the stack.
EDIT:
I know this should not be done, but I'm trying to understand buffer overflows (more realistically the buffer should be of character, given as input by an user), and the goal should be to alter the value of the variable. So what I'm trying to understand is if it's possible to know exactly where the variable actually is in memory.
EDIT2:
Turns out that giving -fno-stack-protector makes it work as expected, so gcc is adding by default some sort of protection in order to avoid buffer overflows
The placement of local variables is a detail of the implementation. They may be placed in any order it deems appropriate.
Attempting to read past the bounds of an array invokes undefined behavior. The inconsistent results you see are a manifestation of that.
As an example, if I run your first code snippet, I do not get 2 as the output. When printing the addresses of each variable, I get:
&integer1=0x7ffcfa6e8c24, &integer2=0x7ffcfa6e8c20
So in my case the implementation puts integer1 after integer2.

Segmentation Fault & printing an array without loops

I'm Just trying to run a simple program to count the number of spaces, digits and other characters using arrays. Below is my program:
void main(){
int digit_holders[10]={0};
int ch;
int i, white_space=0,other=0;
while((ch=getchar())!=EOF){
if(isspace(ch))
white_space++;
else if(isdigit(ch))
digit_holders[ch-'0']++;
else
other++;
}
digit_holders[12]=20;
printf("\n White spaces=%d\n Other=%d\n",white_space,other);
for(i=0;i<=9;i++)
printf("\ndigit_holders[%d]=%d\n",i,digit_holders[i]);
printf("\n digit_holder[12]=%d\n",digit_holders[12]);
}
2 Questions:
Why does digit_holders[12] still manage to print the assigned vale despite it being outside the range? Why doesn't it display a segmentation fault ?The same happens when I change the for loop check to i<=11 it manages to print digit_holders[11]=0 ( which it shouldn't) .. however when I replace 11/10 with 1100 i.e digit_holders[1100] in either of the case, the program crashes ( segmentation fault). Why so ?
Is there an easier way to print the elements of this array without using for loop ?
-Thanks!
There is no range checking in C so it gives it is best shot (I.e enough rope to hang yourself and the rest of the family).
Segmentation fault occurs from the OS. i.e. trying to access memory not assigned to the process.
As I wrote in the comment:
You will need a loop of some kind to print the content of your array in C.
You are assigning the 13th element of an array with only 10 elements declared, its risky to do and will be unstable, but wont necessarily result in a seg fault because if the OS hasnt modified it in the time between write and read, your pointer will resolve the value without error. But again, risky.
If you had declared an array with 13 elements, all 13 will be reserved in memory and there will be no chance of a seg fault. You are likely to get a seg fault if you interrogate an array outside of its declared limits, more so the further you go away from the range you defined.
It's possible to print "out-of-range" array indices in C because digit_holders[12] is handled as though digit_holders were a pointer with an offset of 12 * sizeof(int) added on to it.
This won't necessarily cause a segmentation fault, since the memory address being read might still be earmarked as being "available" to the program. A good example of this is a struct containing an array:
typedef struct {
int some_array[12];
int another_int;
} my_struct;
If you were to read the value of some_array[12], you'd get the contents of another_int instead, since it's stored directly after the last "valid" index of some_array.
As for the printing out of arrays: I'm not aware of any way to print out an array without using a loop in C, though it is possible in some other languages. For example, you could easily print out a list of strings in Python using print(", ".join(["This", "That", "The other"]))

understanding the behaviour of this C program [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
i begin Why the output produce 002?
Thanks for the edit and the answers but I'm still confused.
Here is the code:
#include <stdio.h>
int t[3],i;
int main()
{
for(i=0;i<3;i++)
t[i]=i++;
for(i=0;i<3;i++)
printf("%d",t[i]);
}
002
Can anyone help me understand why it is so?
It's because you incremented your i counter twice in your for-loop (once at t[i] = i++, once at the end statement of your for-loop, i++). That way, the for-loop is executed twice (not three times), once for i = 0 and once for i = 2. Hence your output.
To convince yourself, try adding prints as in
for(i=0;i<3;i++) {
printf("%i ", i);
t[i]=i++;
}
and see how many times your for loop gets executed and for which values of i it does.
Download a copy of the C standard (for example, google for N1570, that will give you the latest freely available version). In that document, look for "sequence point" and read what it says.
In short: Your program is rubbish and could do whatever it likes, for the reasons explained in this document. (Basically, the statement t [i] = i++; invokes undefined behaviour. This is a very special case of a general rule set in the C Standard. C++ and Objective-C have the same rule).
You are incrementing i twice in each iteration. In first iteration i = 0, so t[0] = 0 then you are doing i++ twice. In second iteration i=2 so t[2] = 2 and now loop is ending. t[1] is uninitialized.You are getting 002 because:the first 0 from t[0]the second 0 is garbage value or null value from where t[1] is stored in the memory (in your case it is 0 )and the last 2 from t[2]

why my code has not a limit?

That is my code:
#include<stdio.h>
int main()
{
int vet[10], i;
for(i=30; i<=45; i++)
{
scanf("%d", &vet[i]);
}
for(i=30; i<=45; i++)
printf(" %d ", vet[i]);
for(i=30; i<=45; i++)
printf(" %x", &vet[i]);
return 0;
}
I declared just 10 positions of int type on memory, but i get more, so what happened ?
it is a memory overflow ?
and the type %x is correctly to print the memory adress ?
the imput was:
1
2
3
4
5
6
7
8
9
10 /*It was to be stoped right here !?*/
11
12
13
14
15
16
and returned:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 /*I put space to indent*/
22ff6c 22ff70 22ff74 22ff78 22ff7c 22ff80 22ff84 22ff88 22ff8c 22ff90 22ff94 22ff98 22ff9c 22ffa0 22ffa4 22ffa8
The C language does not check bounds when you access arrays for reading or writing. It is up to the program author to ensure that the program accesses only valid array elements.
In this case, you wrote values to memory addresses outside your declared array. While you may sometimes get a segmentation violation (SIGSEGV) in this case, you may just get "lucky" -- really, unlucky -- and not encounter any problems at runtime.
C doesn't enforce array boundaries. Keeping within the limits is your responsibility in that language - it will let you do plainly wrong things, but it may crash at runtime.
Not only does the C language not check bounds on array accesses with respect to array size, which explains why you are successfully writing to the array 15 times, but C also does not have a mechanism for converting your range of 30 to 45 into the range of the first 10 (or 15?) elements of the array.
So, you are really attempting to write to the 31st through 46th element of the array vet, which has only 10 elements.
C is perfectly happy to let you read from and write to an array past the bounds you set (10, in this case).
Reading past the limit just gives you garbage; writing past it will do all kinds of crazy things and generally crash your program (or, if you are unlucky, overwrite your entire hard drive).
You were lucky with this program, but you should not keep doing that. In C, you are responsible for enforcing the limits of your arrays yourself.
int vet[10] declares a block of ten integers in memory. These memory locations are accessed via vet[0] through vet[9]. Any other access to memory through vet is undefined behavior. Absolutely anything could be within that memory, and you can easily corrupt the rest of your program execution. The compiler trusts you to know better than what you were doing.
As #NigelHarper correctly points out, %p is the official way of printing pointers. It prints in hexadecimal. Pointers could print in decimal, but the number itself is meaningless. Hexadecimal makes the printing more concise, and just as easy to see differences from one address to the next.
It is also possible to use %x for printing a pointer, since all that does is take a value and print it in hexadecimal form.
C does not do bounds checking on arrays and you are accessing an array out of bounds. The possible valid indexes in the array are [0,9], but you are accessing [30,45].
You should modify your code to only access valid indexes:
int SIZE = 10;
int vet[SIZE];
//...
// not for( i = 30; i <= 45; i++ )
for( i = 0; i < SIZE; ++i ) { /* ... */ }
C Language doesn't have support to check the out of bound array accesses. IN c++, if you try to access out of bound array memory location, it will generate Segmentation Fault which causes your process to terminate. As, C doesn't allow it, it is expected behavior.

why this array does not give error? [duplicate]

This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 9 years ago.
I have a program which I expect it to crash but it doesn't. Can you please let me know the reason.
char a[5];
strncpy(a,"abcdefg",7);
a[7] = '\0';
printf("%s\n",a);
Shouldn't the program crash at strncpy() or at a[7]='\0' which is greater than array size of 5. I get output as abcedefg. I'm using gcc compiler.
Size of a array is five char a[5]; and your are assigning at 7th location that is buffer overrun problem and behavior of your code is Undefined at run time.
strncpy(a,"abcdefg",7);
a[7] = '\0';
Both are wrong, you need to defined array like:
#defined size 9 // greater then > 7
char a[size];
notice "abcdefg" need 8 char one extra for \0 null char.
read: a string ends with a null character, literally a '\0' character
In your example, your program has access to memory beyond a (starting address of array) plus 5 as the stack of the program may be higher. Hence, though the code works, ideally it is undefined behavior.
C often assumes you know what your doing, even (especially) when you've done something wrong. There is no bounds to an array, and you'll only get an error if your lucky and you've entered into an undefined memory location and get a segmentation fault. Otherwise you'll be able to access change memory, to whatever results.
You can't give a definition to undefined behaviour, as you are attempting by stating that it should crash. Another example of undefined behaviour that doesn't commonly crash is int x = INT_MAX + 1;, and int x = 0; x = x++ + ++x;. These might work on your system, if only by coincidence. That doesn't stop them from wreaking havoc on other systems!
Consider "Colourless, green ideas sleep furiously", or "The typewriter passed the elephant to the blackness". Do either of these statements make any sense in English? How would you interpret them? This is a similar situation to how C implementations might treat undefined behaviour.
Let us consider what might happen if you ask me to put 42 eggs in my carton that can store at least 12 eggs. The container most certainly has bounds, but you insist that they can all fit in there. I find that the container can only store 12 eggs. You won't know what happens to the 30 remaining eggs, so the behaviour is undefined.

Resources