Solved

simple on arrays in Linux C

Posted on 2002-04-09
34
253 Views
Last Modified: 2012-05-04
main()
{  
     char tmp[10] ;
     tmp[21] = 'k' ;
}
above code will not produce errors (forget the include and all stuff)
but
this following will produce a segmentation fault...why
char *tmp ;
*(tmp+100) = 'k' ;

0
Comment
Question by:kiranghag
  • 14
  • 11
  • 4
  • +5
34 Comments
 
LVL 4

Expert Comment

by:newmang
ID: 6927622
In the first case you are allocating an array of 10 bytes called tmp. You are then copying the value 'k' to the byte that is 22 bytes (array numbering starts at 0) from the address of first element in tmp. This is perfectly legal in C as the language has no bounds checking for arrays. By doing this you are writing over another area of memory which may contain anthing, another variable, some code, the stack or whatever depending on the layout of your binary. The chances are that the area that you are over-writing is within your own executable and therefore although it may (will) cause unpredictable errors in the program operation the operating system will not warn you that you have done something dumb.

In the second case you declare a pointer of type character and name it tmp. This only allocates a pointer variable not an area to which it points. In most cases uninitialised pointers are set to 0x00 and therefore in your next step you are attempting to write to an address that you do not have rights to write to, hence the core dump.

You should be doing

char * tmp;
tmp=(char *)malloc(some_size);
do_something_with_the_memory.......
free(tmp);


Cheers - Gavin
0
 
LVL 4

Expert Comment

by:newmang
ID: 6927624
Sorry about the typos - new keyboard!
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6927631
if i say
char *tmp = 10 ; //initialization

and then *tmp = 'k' ;
it still gives fault.
my point is whnever i use a pointer to do some operation like this it faults. why/

dear friend, this i am doing to know how its done internally. i am otherwise very clear abt the pointers and such stuff.
0
 
LVL 5

Expert Comment

by:tzxie2000
ID: 6927751
if you set the tmp to 10,it still in an undefined area.
the most probability is that it point to the syste area or some place not under the memory area about your program.
this will cause the system error.
if you try the code before:

main()
{
char * a;
char b[100];
a=b+200;
*a='\0';
}

it is almost like the first code your write and it will not cause a segment fault at all.

as you set the point a to b+200,the pointer a is set to the memroy area where your program can control or being malloced by system for your program.so it would not cause a segment fault.but it will destroy the data.
it is one of the most posible error the programmer maked and it is hard to be found as the error will display always at the point as you want to use the data after it.
look at it

main()
{
 char a[10];
 char b;

 memset(a,0,100);
 printf("%c",b);
}

the b will be printf out by 0,and if b is an control var,it will be more difficult to find the error
0
 
LVL 5

Expert Comment

by:ecw
ID: 6929710
Read a book on OS design, specifically the chapters on memory management.

If the address you are accessing is not mapped into your address space, a hardware exception is generated, the cpu jumps into some sort of supervisory mode, and starts executing the trap handler dedicated to that exception.  This is part of the OS, the OS says uh-oh you've been naughty, and uses whatever mechanism it has to terminate the program, on UNIX, a segmentation violation.
0
 
LVL 4

Expert Comment

by:newmang
ID: 6929767
kiranqhaq

The problem with your statement

char *tmp = 10 ; //initialization

is that you are setting a pointer to point to absolute address 10 and this is not an area of memory available to your program - hence the OS will protect itself by seg faulting
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6931042
newmang>
do u mean to say setting *tmp = 10 maps the address into IVT? then u are wrong, it maps to 10 in the data segment.

i am aware that when I cross array bounds, segfault may or may not occur. ut whenever I try to do it with pointers (not arrays) i get segfault. and i want to know why that happens. does the compiler has any special treatment for arrays and pointers
0
 
LVL 4

Expert Comment

by:newmang
ID: 6932805
kiranqhaq

I did not say that it mapped into the IVT, it does map into to address 10 in the text segment but the low end of this segment is marked read-only as it contains code and therefore an attempt to write to it causes the segfault.

Cheers - Gavin
0
 
LVL 4

Expert Comment

by:newmang
ID: 6932808
To answer your second point, no the compilerdoes not have any "special" treatment for arrays and pointers. With C, as you have found out, you are on your own to a large extent.

Cheers - Gavin
0
 
LVL 1

Expert Comment

by:Shivshankar
ID: 6933449
When you have declared local arrays, most of the compilers, put them in the stack(except for those compilers which treat arrays as static). So... what you're doing is just modifying the contents of stack which are not referenced to until your program terminates. Write a very big program with all stuff and in every place mis-use/cross the boundary line and you'll end up with a system crash. If you don't, give your compiler a pat at its back. You're simply lucky!!!

Nothing else can define this phenomenon.
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6943959
newmang>>> i dont think any compilers puts code in the data segment (what is text segment? is it data segment for u? ) . why it should do that?
0
 
LVL 4

Expert Comment

by:newmang
ID: 6944105
kiranqhaq

my terminology and/or explanation may not have been clear enough.. let me revisit it..

In the address space of the process the data would be laid out like this

LOW ADDRESS
text segment
data segment
stack segment
HIGH ADDRESS

The text segment contains code and read-only data and is read only. the data segment contains initialised and uninitialised data (static variables). The size of this area can be changed with the brk() function. The stack segment is used to hold automaitic variables.

When you dereference your pointer without an intervening malloc it will "point" into an address in the low memory text segment and cause the core.

Hope this make it clearer.

Cheers - Gavin
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6944108
your notions of read only segments seems to be from protected mode world. they do not well apply to low level C world
0
 
LVL 4

Expert Comment

by:newmang
ID: 6944114
kiranqhaq

Its got nothing to do with protected mode as far as I can see, its the standard binary layout for a Unix (Solaris, Linux, AIX) process in memory irrespective of the source language (it's a binary remember).

Cheers - Gavin
0
 
LVL 2

Expert Comment

by:obg
ID: 6944648
Lots of comments... Hope that you can forgive if this has been said already.

Linux uses memory protection and address 10 is simply part of the protected memory area, while a couple of bytes up in the stack is most likely not protected (as long as you don't step to high up). Be careful though, cause you might overwrite some return addresses. The same goes for global variables, which will end up in an unprotected data area in memory.
0
 
LVL 2

Expert Comment

by:Slordak
ID: 6948935
The discussion here seems to have already completely exhausted this issue, but if there is still any confusion...

This seems to be a classical error of declaring a pointer and treating the pointer as if it itself had memory allocated for storing a value, i.e.:

char tmp1;
vs.
char *tmp2;

In the first case, the compiler allocates (stack) storage for a single character variable.  In the second case, the compiler allocates space for a character pointer.  This pointer, of course, can point to various memory locations, but declaring a pointer doesn't automatically grant one the storage for a variable of this type (declaring a char pointer does not create a character to which it points; you can certainly make it point to a valid character variable, though).  Example with above declarations:

tmp1 = 'a';   /* Good. */
tmp2 = (some random address);
*tmp2 = 'b';  /* Almost certainly going to break! */

If you want actual value storage, declare a non-pointer variable (or an array of such variables), or else use malloc().
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6958914
nope, i am satisfied...
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 10

Author Comment

by:kiranghag
ID: 6958916
nope, i am not satisfied...
0
 
LVL 4

Expert Comment

by:newmang
ID: 6958918
Now I'm confused...are you satisfied or are you not satisfied (if not, why not)?
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6958936
i am not,
cause the folks are explaining me how to use pointers and not how going abt solving my doubt. though i am not an expert on pointers and c , i have worked quite a bit on it.
please read the problem again

HTH
Kiran
http://kiran7.freeservers.com

0
 
LVL 4

Expert Comment

by:newmang
ID: 6958942
Now I'm confused...are you satisfied or are you not satisfied (if not, why not)?
0
 
LVL 4

Expert Comment

by:newmang
ID: 6958956
Kiran

Refer to my first post. This explained what you were seeing. Subsequent postings have fleshed this out and/or explained the same result in different terms.

In summary..

Your first code snippet writes beyond the bounds of pre-allocated memory within the writeable area of your process in memory - the result, as I said before, is that the operation succeeds BUT subsequent problems may occure depending on what was in the area you over-wrote.

In your second code snippet you attempt to use an uninitialised pointer to address memory to be written to. Because you have not allocated memory for the pointer to point to and thereby place a valid memory address in that pointer it still contains 0 and therefore you are attempting to write to memory in an area of your process image which is marked read-only by the operating system and therefore your process will be segment faulted by the OS in an attempt by the OS to protect itself.

Gavin
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6958958
tomorrow, i'll come with some eloboration on this question, plz wait.
0
 
LVL 1

Expert Comment

by:tapasmondal
ID: 6970414
On the 2nd part, you have defined a pointer of char.It holds the address of the variable. It can't any area of memory. To do this you have to write like as:
tmp=(char *)malloc(N*sizeof(char));
N= length of the area.

thanks,
tapas

0
 
LVL 4

Expert Comment

by:newmang
ID: 6970483
tapasmondal

You should post comments not answers, especially when you are merely repeating information provided previously (on a number of occasions) Unless your contribution is the definitive answer and no-one else has already provided the information then you should comment and let the question writer decide as to whether the question is answered adequately.

Cheers - Gavin
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6972820
this is NOTTTTT an answer
i am here to study how to alloc mem
i want a specific answer
plz read the wuestion again and again
0
 
LVL 4

Expert Comment

by:newmang
ID: 6975779
kiranqhaq

Your original question was in regard to why tow different pieces of code produced different behaviours. These questions have been addressed at length and answered many times over.

You now say that you want to study how to allocate memory - this too has been answered in previous posts by me and others but to summarise.

If you want to dynamically allocate memory in your C program you perform the following steps.

1) Declare a pointer of the type required as follows.
char * ptr_fred;

2) Note that at this stage the pointer does NOT point to a valid area of memory and therefore you cannot use the pointer to address memory.

3) Allocate memory and set the pointer to point to that memory as follows
ptr_fred=(char *)malloc(amount_of_memory_required);

4) Check that the pointer is valid (malloc returns NULL on error)
if(ptr_fred==NULL)
   error_state....

5) User *ptr_fred to access the memory

6) Free up the memory as follows:
free(ptr_fred);

7) The pointer variable is once again no longer able to be used to reference memory.

Gavin


0
 
LVL 2

Expert Comment

by:obg
ID: 6979829
Ok, then I might add that when a program starts up it gets a designated data area in memory from the system. Every attempt to write outside this area will result in a segmentation fault. Memory allocations (malloc) will reserve a block of memory within this area. Now, your example
    char tmp[10];
    tmp[21] = 'k';
will put 'k' on the stack where all other local variables are stored. Hopefully you will not destroy any return addresses. When you call a function, the function arguments are first pushed from right to left. Then the return address gets pushed onto the stack. After that the jump is made. In the function the current stack pointer (which points to the return address) is stored, and afterwards it gets decreased (the stack grows downwards) to reserve a hole in the stack for local variables. When the function finnishes, it restores the original stack pointer (jumps the local variables) and jumps to where the stack pointer pointer (!) points (it returns). The caller will then clean up the stack from it's previously pushed function arguments.

If you had done something like:
    char *tmp;
    tmp = malloc(10);
    tmp[21] = 'k';
I THINK you would not get an error since you're probably still within allowed address space, though not space reserved for tmp.

- Hope that some this could help you!
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6985608
Doubt solved....
first I ran this

int main( void ) {
       int *a ;
       *a = 10 ;
}

no seg fault...okay

now this

int main( void ) {
       int *a = 10 ;
       *a = 10 ;
}

now there is a seg fault
now did this

int main( void ) {
       int *a ;
       *a = 10 ;
       printf( "\n%d\n", a ) ;
}

i got some int value, say xx

now again did this

int main( void ) {
       int *a = xx ;
       *a = 10 ;
       printf( "\n%d\n", a ) ;
}

no seg fault....that means now my pointer was explicitly initialised in a data $And that for me, proves that compiler doesn't treat pointers and array name as $thanks everybdy
give ur comments, so that i can close the question
0
 
LVL 2

Expert Comment

by:obg
ID: 6985661
Ok. When you declare a variable (doesn't matter if it's a pointer), it's value is undefined. Since local variables are placed on the stack, they can contain anything. You never know what's been there before...

Sorry, but I did not understand what this proves to you...
0
 
LVL 4

Expert Comment

by:newmang
ID: 6987529
kiran

I'm glad we got this sorted out.

The first two code snippets in your last posting illustrate what I and others have been saying all along regarding random memory reference and dereferencing unallocated pointers.

The last two code snippets will never produce a segmentation fault because your are only printing the address of the pointer in your printf statements NOT the memory the pointer points to - you are not dereferencing the pointer. You would be better off in these cases using a printf("%0X\n",a); statement to get the address in hex.

Cheers - Gavin
0
 
LVL 2

Expert Comment

by:obg
ID: 6988116
What??? (Refering to the last paragraph of newmang's comment.)

The segmentation fault has nothing to do with the printf, but with the *a = 10;! I find it very likely that at least the 2nd last snippet will produce a segmentation fault.

But I agree that the "conclusions" are just what we've been saying all along. (Except that I don't understand the proof in the last sentence.)
0
 
LVL 10

Author Comment

by:kiranghag
ID: 6989494
does the compiler has
any special treatment for arrays and pointers?

that was my doubt in my third comment.

but now i know it doesn't...

0
 
LVL 4

Accepted Solution

by:
newmang earned 50 total points
ID: 6992388
obg

You are correct re the second to last snippet - I overlooked the dereference of the pointer when looking at the printf. The last snippet won't produce a seg fault because the initialisation of the pointer (int *a = xx) will cause the compiler to generate code to allocate the memory and link the pointer to it.

kiran

The compiler does not have any "special" treatment for arrays and pointers as we have explained previously, the compiler really doesn't know about arrays - it knows a base address and an amount of memory that you, the coder, refer to as ana array - the compiler assumes that you will take care of making sure you do not address beyond the bounds of the array in either direction (it is entirely possible to undershoot an "array" as well as the more normal error of addressing past the end of the area allocate), nor does it have any "special" handling for pointers.

C is a good language in that it allows you to do just about anything you want to but that is also one of it's drawbacks if you are not careful.

Cheers - Gavin
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and reading files in the C programming language.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now