Realloc destroys?

I

ifmusic

I used to think that i knew to program in C but this problem is making
me thing otherwise.
i'm trying to do something trivial, i suppose.
i have this struct:

typedef struct{
int socket;
char ip[16];
}peers;

in a main() i malloc this way:
Peers=malloc(sizeof(peers));
Then, my program would eventually want to save more "peers" so
i said, why dont i Realloc this thing x2 x3 x4 x5 and so on.. as
needed. So i created this function:

peers* ingresaripsock(peers* lista,int sock, char ip[16],int *tm)
{
int offset= (*tm)++;

if (offset>0) lista = realloc(lista,offset * sizeof(peers)+1);

strcpy((lista + offset)->ip, ip);
(lista + offset)-> socket=sock;

return lista;
}

i print the results with:

void imprimirpeers(peers* lista, int tm){
int i=0;

for(i=0;i<tm;i++){
printf("Ip: %s - Sock: %d\n",(lista + i) ->ip , (lista + i)
->socket);
}
}


but when i printf the Results, it's all weird data. I believe the
problem is around the Realloc becuase i tried this code but instead of
using realloc i malloc'd from the first time with space for like 20
positions (commented the realloc part in the function) and it worked
just fine. But i want to use what i Really need, dont want to do malloc
( 20000000) and use a couple of bytes...


Please i really need some help-
 
M

Martin Ambuhl

if (offset>0) lista = realloc(lista,offset * sizeof(peers)+1);

This is a severe mistake. Never use the form
ptr = realloc(ptr, size);
Instead have the results of the realloc() assigned to a temporary
variable to give you at least the option of what to do if realloc fails.
 
I

ifmusic

yes, after writing the post, i read some of that, i'm switchin to a
pointer to pointer data structure. hope it works that way.
Thanks.
 
C

Christian Bau

I used to think that i knew to program in C but this problem is making
me thing otherwise.
i'm trying to do something trivial, i suppose.
i have this struct:

typedef struct{
int socket;
char ip[16];
}peers;

in a main() i malloc this way:
Peers=malloc(sizeof(peers));
Then, my program would eventually want to save more "peers" so
i said, why dont i Realloc this thing x2 x3 x4 x5 and so on.. as
needed. So i created this function:

peers* ingresaripsock(peers* lista,int sock, char ip[16],int *tm)
{
int offset= (*tm)++;

if (offset>0) lista = realloc(lista,offset * sizeof(peers)+1);

Your calculation how many bytes are needed looks interesting.
 
B

Barry Schwarz

I used to think that i knew to program in C but this problem is making
me thing otherwise.
i'm trying to do something trivial, i suppose.
i have this struct:

typedef struct{
int socket;
char ip[16];
}peers;

in a main() i malloc this way:
Peers=malloc(sizeof(peers));
Then, my program would eventually want to save more "peers" so
i said, why dont i Realloc this thing x2 x3 x4 x5 and so on.. as
needed. So i created this function:

peers* ingresaripsock(peers* lista,int sock, char ip[16],int *tm)

Is *tm a count of how may structures your currently have space for?
{
int offset= (*tm)++;

offset is the original value of *tm.
if (offset>0) lista = realloc(lista,offset * sizeof(peers)+1);

What did you think the +1 does. What you have done, if realloc
succeeds, is allocate space for the same number of structures plus one
more byte. You did not allocate space for an extra struct. Did you
really mean
... = realloc(lista, (offset+1) * sizeof(peers));
strcpy((lista + offset)->ip, ip);

As it stands now, this invokes undefined behavior. lista points to an
allocated area capable of holding offset structures. The structures
are numbered 0, 1, ..., offset-1. You are now writing beyond the end
of your allocated area.
(lista + offset)-> socket=sock;

return lista;
}

i print the results with:

void imprimirpeers(peers* lista, int tm){
int i=0;

for(i=0;i<tm;i++){
printf("Ip: %s - Sock: %d\n",(lista + i) ->ip , (lista + i)
->socket);
}
}


but when i printf the Results, it's all weird data. I believe the
problem is around the Realloc becuase i tried this code but instead of
using realloc i malloc'd from the first time with space for like 20
positions (commented the realloc part in the function) and it worked
just fine. But i want to use what i Really need, dont want to do malloc
( 20000000) and use a couple of bytes...


Please i really need some help-


<<Remove the del for email>>
 
I

ifmusic

Thank you all for all the feedback,
now i have a pointer to pointer structure.

typedef struct{
int socket;
char id[16];
}reqs;

reqs** ingresaridsock(reqs** lista,int sock, char id[16],int *tm){
int i;
reqs* aux;
reqs **temp;
int offset= (*tm)++;
aux = malloc(sizeof(reqs));
if (offset > 0 ){
if ((temp = realloc(lista, (offset+1) * sizeof(*lista)))==NULL)
exit(1);
lista=temp;}
strcpy(aux->id, id);
aux->socket= sock;
lista[offset]= aux;
return lista;

Now, it seems to work just fine. BUT!, i add 1,2,3,4 and on the fifth
item,
i get Segmentation Fault! Knowing that i'm not freeing memory as i
should
shouldn't it be possible to store more than 4 miserable items without
freeing?!.

thanks again.

Barry Schwarz ha escrito:
I used to think that i knew to program in C but this problem is making
me thing otherwise.
i'm trying to do something trivial, i suppose.
i have this struct:

typedef struct{
int socket;
char ip[16];
}peers;

in a main() i malloc this way:
Peers=malloc(sizeof(peers));
Then, my program would eventually want to save more "peers" so
i said, why dont i Realloc this thing x2 x3 x4 x5 and so on.. as
needed. So i created this function:

peers* ingresaripsock(peers* lista,int sock, char ip[16],int *tm)

Is *tm a count of how may structures your currently have space for?
{
int offset= (*tm)++;

offset is the original value of *tm.
if (offset>0) lista = realloc(lista,offset * sizeof(peers)+1);

What did you think the +1 does. What you have done, if realloc
succeeds, is allocate space for the same number of structures plus one
more byte. You did not allocate space for an extra struct. Did you
really mean
... = realloc(lista, (offset+1) * sizeof(peers));
strcpy((lista + offset)->ip, ip);

As it stands now, this invokes undefined behavior. lista points to an
allocated area capable of holding offset structures. The structures
are numbered 0, 1, ..., offset-1. You are now writing beyond the end
of your allocated area.
(lista + offset)-> socket=sock;

return lista;
}

i print the results with:

void imprimirpeers(peers* lista, int tm){
int i=0;

for(i=0;i<tm;i++){
printf("Ip: %s - Sock: %d\n",(lista + i) ->ip , (lista + i)
->socket);
}
}


but when i printf the Results, it's all weird data. I believe the
problem is around the Realloc becuase i tried this code but instead of
using realloc i malloc'd from the first time with space for like 20
positions (commented the realloc part in the function) and it worked
just fine. But i want to use what i Really need, dont want to do malloc
( 20000000) and use a couple of bytes...


Please i really need some help-


<<Remove the del for email>>
 
I

ifmusic

Here is something new,
if the first time i malloc(15*sizeof(*Reqs)) it works fine. So i
commented the Realloc part in the function i tried it. But Something i
did not expect ,happened, it didn't just stored 15 items but it seemed
to be "endless", i stored tons of items as if there was no need for a
Realloc. WHY?!.

(e-mail address removed) ha escrito:
Thank you all for all the feedback,
now i have a pointer to pointer structure.

typedef struct{
int socket;
char id[16];
}reqs;

reqs** ingresaridsock(reqs** lista,int sock, char id[16],int *tm){
int i;
reqs* aux;
reqs **temp;
int offset= (*tm)++;
aux = malloc(sizeof(reqs));
if (offset > 0 ){
if ((temp = realloc(lista, (offset+1) * sizeof(*lista)))==NULL)
exit(1);
lista=temp;}
strcpy(aux->id, id);
aux->socket= sock;
lista[offset]= aux;
return lista;

Now, it seems to work just fine. BUT!, i add 1,2,3,4 and on the fifth
item,
i get Segmentation Fault! Knowing that i'm not freeing memory as i
should
shouldn't it be possible to store more than 4 miserable items without
freeing?!.

thanks again.

Barry Schwarz ha escrito:
I used to think that i knew to program in C but this problem is making
me thing otherwise.
i'm trying to do something trivial, i suppose.
i have this struct:

typedef struct{
int socket;
char ip[16];
}peers;

in a main() i malloc this way:
Peers=malloc(sizeof(peers));
Then, my program would eventually want to save more "peers" so
i said, why dont i Realloc this thing x2 x3 x4 x5 and so on.. as
needed. So i created this function:

peers* ingresaripsock(peers* lista,int sock, char ip[16],int *tm)

Is *tm a count of how may structures your currently have space for?
{
int offset= (*tm)++;

offset is the original value of *tm.
if (offset>0) lista = realloc(lista,offset * sizeof(peers)+1);

What did you think the +1 does. What you have done, if realloc
succeeds, is allocate space for the same number of structures plus one
more byte. You did not allocate space for an extra struct. Did you
really mean
... = realloc(lista, (offset+1) * sizeof(peers));
strcpy((lista + offset)->ip, ip);

As it stands now, this invokes undefined behavior. lista points to an
allocated area capable of holding offset structures. The structures
are numbered 0, 1, ..., offset-1. You are now writing beyond the end
of your allocated area.
(lista + offset)-> socket=sock;

return lista;
}

i print the results with:

void imprimirpeers(peers* lista, int tm){
int i=0;

for(i=0;i<tm;i++){
printf("Ip: %s - Sock: %d\n",(lista + i) ->ip , (lista + i)
->socket);
}
}


but when i printf the Results, it's all weird data. I believe the
problem is around the Realloc becuase i tried this code but instead of
using realloc i malloc'd from the first time with space for like 20
positions (commented the realloc part in the function) and it worked
just fine. But i want to use what i Really need, dont want to do malloc
( 20000000) and use a couple of bytes...


Please i really need some help-


<<Remove the del for email>>
 
O

Old Wolf

typedef struct{
int socket;
char id[16];
}reqs;

reqs** ingresaridsock(reqs** lista,int sock, char id[16],int *tm){
int i;
reqs* aux;
reqs **temp;
int offset= (*tm)++;
aux = malloc(sizeof(reqs));
if (offset > 0 ){
if ((temp = realloc(lista, (offset+1) * sizeof(*lista)))==NULL)
exit(1);
lista=temp;}

You never allocate anything when *tm was 0.
If lista were NULL (or an array of size 0), then you would
cause undefined behaviour.
strcpy(aux->id, id);
aux->socket= sock;
lista[offset]= aux;
return lista;

Now, it seems to work just fine. BUT!, i add 1,2,3,4 and on the
fifth item, i get Segmentation Fault!

If the above was not the problem, then perhaps you have a buffer
overflow in the strcpy, or some other heap corruption. Can you
post a complete, compilable program that demonstrates the problem?

BTW, please don't top-post ( http://en.wikipedia.org/wiki/Top-posting )
 
I

ifmusic

There's no problem about the tm being 0.

the thing with posting the whole thing is that i don't know how you're
gonna test it. I'm testing it with 3 vmwares as clients and 1 vmware as
server which is storing the info.

Again, something that's still bugging me is the "endless" list i'm
getting...

if you want i can mail you the code.

Thanks for the help-
 
B

Barry Schwarz

Thank you all for all the feedback,
now i have a pointer to pointer structure.

typedef struct{
int socket;
char id[16];
}reqs;

reqs** ingresaridsock(reqs** lista,int sock, char id[16],int *tm){
int i;
reqs* aux;
reqs **temp;
int offset= (*tm)++;
aux = malloc(sizeof(reqs));
if (offset > 0 ){
if ((temp = realloc(lista, (offset+1) * sizeof(*lista)))==NULL)
exit(1);
lista=temp;}
strcpy(aux->id, id);
aux->socket= sock;
lista[offset]= aux;
return lista;

Now, it seems to work just fine. BUT!, i add 1,2,3,4 and on the fifth
item,
i get Segmentation Fault! Knowing that i'm not freeing memory as i
should
shouldn't it be possible to store more than 4 miserable items without
freeing?!.

On which statement does the seg fault occur?

How are you calling this function? Show us main.


<<Remove the del for email>>
 
M

Marc Thrun

Here is something new,
if the first time i malloc(15*sizeof(*Reqs)) it works fine. So i
commented the Realloc part in the function i tried it. But Something i
did not expect ,happened, it didn't just stored 15 items but it seemed
to be "endless", i stored tons of items as if there was no need for a
Realloc. WHY?!.

(e-mail address removed) ha escrito:
If you write more items than you have allocated space for, you invoke
undefined behaviour which allows anything to happen. It might even seem
to work though you might corrupt some other memory.
 
I

ifmusic

but why? all i did is :
in the Main i declared te pointers and i malloc'd these "endless"
pointer to
15, so i thought, ok i should have space to store 15 entries. Found
out, i can store way more than that.
"undefined behaviour", i think i was trying to do Something Well
defined But when i tried to store a couple of entries i got my
beautiful segmentation code, that's why i malloc'd 15, though i never
expected this to happen.

I'll try to post an extract of my program with everything that could be
related to the List of pointers to pointers.

Thank you all for answering so fast!
 
I

ifmusic

that's a good question.
-after checking it out, it does not Seg Fault when i'm storing but
actually
when i'm printing the results. I mean, after adding the fifth item , i
call for a
printing function which is basically a For going through the structure,
but
it hangs (seg faults) inmediatelly, not in the second, fourth or
fifth....

i'll give you more info soon.
But tell me if you got any clues.
 
K

Keith Thompson

but why? all i did is :
in the Main i declared te pointers and i malloc'd these "endless"
pointer to
15, so i thought, ok i should have space to store 15 entries. Found
out, i can store way more than that.
"undefined behaviour", i think i was trying to do Something Well
defined But when i tried to store a couple of entries i got my
beautiful segmentation code, that's why i malloc'd 15, though i never
expected this to happen.

I'll try to post an extract of my program with everything that could be
related to the List of pointers to pointers.

Thank you all for answering so fast!

Please post properly. Google makes this unnecesarily difficult, but
the instructions have been posted here over 1000 times (that's not an
exaggeration). Here they are again:

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Please complain to Google about their broken interface.

Based on your description, and without looking at whatever code
you posted earlier, you might find this instructive:

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int *ptr;

ptr = malloc(5 * sizeof *ptr);
if (ptr == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}

/*
* ptr now points to an allocated array of 5 integers.
* ptr[0] refers to element 0 of the array.
* ptr[4] refers to the last element of the array.
*/

ptr[0] = 37;
printf("ptr[0] = %d\n", ptr[0]);
/*
* Ok so far.
*/

ptr[4] = 42;
printf("ptr[4] = %d\n", ptr[4]);
/*
* Still ok; we've just stored a value in the last
* allocated element of the array.
*/

ptr[5] = 77;
printf("ptr[5] = %d\n", ptr[5]);
/*
* This invokes undefined behavior by writing past the end
* of the allocated memory.
*/

return 0;
}

When I compiled and ran this program, I got the following output:

ptr[0] = 37
ptr[4] = 42
ptr[5] = 77

As soon as I assigned a value to ptr[5], I invoked undefined behavior,
because I wrote to memory that I didn't necessarily own. "Undefined
behavior" does *not* mean that the program is going to fail; it means
that, as far as the standard is concerned, the program can do
literally anything -- including behaving exactly as you might think it
should.

You said you thought you had space for 15 entries, but you found you
could store more than that. Storing more than 15 entries is
(presumably) an error, but the implementation isn't obligated to
detect the error. It can just go ahead and store the additional data
wherever you tell it to, even if it steps on other data (other
variables, system data, whatever) while it's doing so.

The responsibility for avoiding undefined behavior is entirely yours.
 
I

ifmusic

Wow, that's crazy, never thought C provided such little protection.
Ok, now i get that even though i could store all this items i should
try to find out how to allocate and make it work properly too.
now, this, is where i need some help with...
Keith Thompson ha escrito:
but why? all i did is :
in the Main i declared te pointers and i malloc'd these "endless"
pointer to
15, so i thought, ok i should have space to store 15 entries. Found
out, i can store way more than that.
"undefined behaviour", i think i was trying to do Something Well
defined But when i tried to store a couple of entries i got my
beautiful segmentation code, that's why i malloc'd 15, though i never
expected this to happen.

I'll try to post an extract of my program with everything that could be
related to the List of pointers to pointers.

Thank you all for answering so fast!

Please post properly. Google makes this unnecesarily difficult, but
the instructions have been posted here over 1000 times (that's not an
exaggeration). Here they are again:

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Please complain to Google about their broken interface.

Based on your description, and without looking at whatever code
you posted earlier, you might find this instructive:

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int *ptr;

ptr = malloc(5 * sizeof *ptr);
if (ptr == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}

/*
* ptr now points to an allocated array of 5 integers.
* ptr[0] refers to element 0 of the array.
* ptr[4] refers to the last element of the array.
*/

ptr[0] = 37;
printf("ptr[0] = %d\n", ptr[0]);
/*
* Ok so far.
*/

ptr[4] = 42;
printf("ptr[4] = %d\n", ptr[4]);
/*
* Still ok; we've just stored a value in the last
* allocated element of the array.
*/

ptr[5] = 77;
printf("ptr[5] = %d\n", ptr[5]);
/*
* This invokes undefined behavior by writing past the end
* of the allocated memory.
*/

return 0;
}

When I compiled and ran this program, I got the following output:

ptr[0] = 37
ptr[4] = 42
ptr[5] = 77

As soon as I assigned a value to ptr[5], I invoked undefined behavior,
because I wrote to memory that I didn't necessarily own. "Undefined
behavior" does *not* mean that the program is going to fail; it means
that, as far as the standard is concerned, the program can do
literally anything -- including behaving exactly as you might think it
should.

You said you thought you had space for 15 entries, but you found you
could store more than that. Storing more than 15 entries is
(presumably) an error, but the implementation isn't obligated to
detect the error. It can just go ahead and store the additional data
wherever you tell it to, even if it steps on other data (other
variables, system data, whatever) while it's doing so.

The responsibility for avoiding undefined behavior is entirely yours.
 
I

ifmusic

sorry about the posting thing, i hadnt realized...
hope this is the correct way...

Now It's killing me! Why does it crash on the Fifth element!
why not first?! or after a lot?!

Keith Thompson ha escrito:
but why? all i did is :
in the Main i declared te pointers and i malloc'd these "endless"
pointer to
15, so i thought, ok i should have space to store 15 entries. Found
out, i can store way more than that.
"undefined behaviour", i think i was trying to do Something Well
defined But when i tried to store a couple of entries i got my
beautiful segmentation code, that's why i malloc'd 15, though i never
expected this to happen.

I'll try to post an extract of my program with everything that could be
related to the List of pointers to pointers.

Thank you all for answering so fast!

Please post properly. Google makes this unnecesarily difficult, but
the instructions have been posted here over 1000 times (that's not an
exaggeration). Here they are again:

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Please complain to Google about their broken interface.

Based on your description, and without looking at whatever code
you posted earlier, you might find this instructive:

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int *ptr;

ptr = malloc(5 * sizeof *ptr);
if (ptr == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}

/*
* ptr now points to an allocated array of 5 integers.
* ptr[0] refers to element 0 of the array.
* ptr[4] refers to the last element of the array.
*/

ptr[0] = 37;
printf("ptr[0] = %d\n", ptr[0]);
/*
* Ok so far.
*/

ptr[4] = 42;
printf("ptr[4] = %d\n", ptr[4]);
/*
* Still ok; we've just stored a value in the last
* allocated element of the array.
*/

ptr[5] = 77;
printf("ptr[5] = %d\n", ptr[5]);
/*
* This invokes undefined behavior by writing past the end
* of the allocated memory.
*/

return 0;
}

When I compiled and ran this program, I got the following output:

ptr[0] = 37
ptr[4] = 42
ptr[5] = 77

As soon as I assigned a value to ptr[5], I invoked undefined behavior,
because I wrote to memory that I didn't necessarily own. "Undefined
behavior" does *not* mean that the program is going to fail; it means
that, as far as the standard is concerned, the program can do
literally anything -- including behaving exactly as you might think it
should.

You said you thought you had space for 15 entries, but you found you
could store more than that. Storing more than 15 entries is
(presumably) an error, but the implementation isn't obligated to
detect the error. It can just go ahead and store the additional data
wherever you tell it to, even if it steps on other data (other
variables, system data, whatever) while it's doing so.

The responsibility for avoiding undefined behavior is entirely yours.
 
D

Default User

sorry about the posting thing, i hadnt realized...
hope this is the correct way...


Not quite. Your replies belong following or inspersed with the quotes.
See almost every other post on the newsgroup for the correct way.




Brian
 
K

Keith Thompson

sorry about the posting thing, i hadnt realized...
hope this is the correct way...

Please don't top-post. Your response belongs below any quoted text,
and you should trim anything that's not relevant to your response.
See most of the articles in this newsgroup for exmaples.
Now It's killing me! Why does it crash on the Fifth element!
why not first?! or after a lot?!

That's the nature of undefined behavior. As long as you stay within
the bounds of your array, you're fine. As soon as you start stepping
on memory outside your array, you invoke undefined behavior, which
means it can do anything. (The standard joke here is that it can
legally make demons fly out your nose.) One of the infinitely many
possible behaviors is that it can behave "correctly".

Once you've determined that your code invokes undefined behavior,
there's usually no point in worrying about why it behaves in a
particular way. Just fix the code.
 
N

Niklas Norrthon

sorry about the posting thing, i hadnt realized...
hope this is the correct way...

Now It's killing me! Why does it crash on the Fifth element!
why not first?! or after a lot?!

That's the way undefined behavior in C works. It might even not
crash at all, or it might crash only when your boss is looking,
or it might format your hard drive.

The C language defines how a compiled program should behave, and
it defines some boundaries your code may not cross. Usually there
are no checks neither at compile time nor run time that those
boundaries are not crossed. But after they are crossed absolutly
anything could happen according to the standard.

One of those boundaries is memory. The standard say you may
use memory you own, and you must not use memory you don't own.

In the real world with "normal" platforms (Unix, Windows, Mac
et cetera), undefined behavior usally leads to some pretty
predictable behavior, when you are familiar with the
implementation.

For example, when you start a program on a typical 32 bit unix
(or windows) platform that program (or process actually) has its
own 4 GB "virtual" address starting at 0x00000000 and ending at
0xFFFFFFFF. The operating system maps some of those virtual
addresses to physical memory, and some addresses are not mapped
at all. Several processes running simultaniously could have
a mapping for the same virtual address, but then it would map
to different physical locations. (All this is handled by the
operating system, and is usually nothing a programmer would have
to care about). This means that it is pretty hard for a C program
to write data into memory owned by another running process. So in
theory undefined behavior could lead to another unrelated process
to crash, that is quite unlikely to happen.

By the way, what does "crash" mean? In unix, sometimes a process
suddenly writes a message to stderr saying something like:
"segmentation fault", writes a file named "core" somewhere and
then disappears entirely from the face of earth. (in windows
a message dialog pops up instead, saying "access violation..."). Where
does that message come from? It is unlikely that are any statements
like fprintf(stderr, "segmentation fault\n"); in the programs
source code. The answer is that it was the operating system which
aborted the program and wrote the message (or showed the message
dialog). "Segmentation fault" usally means that the process tried
to read from or write to memory a virtual memory address that
either was not mapped to any physical address, or mapped to
an address which was protected from that kind of access (executable
code is usally read-only for example).

The memory for a running process could be organized like this:
+-----------------------------------+
| | 0xFFFFFFFF
| |
| |
| |
| Unmapped memory addresses |
| |
| |
| |
| |
+-----------------------------------+
| |
| |
| |
| |
| Mapped memory addresses |
| |
| |
| |
| |
| |
| |
| |
| |
+-----------------------------------+
| |
| |
| Unmapped memory addresses |
| |
| |
| | 0x00000000
+-----------------------------------+

A program trying to read or write to an unmapped memory address
invokes undefined behavior, and anything *could* happen, but
in reallity a pretty predictable "crash" is the result.

But the C language standard does not say: "You may not write
to unmapped addresses". It says that you may not write to memory
not "owned" or "allocated" by the program. All unmapped memory
is also not owned by the program, but also a large portion
of the mapped memory is not owned by the program. A read or
write operation to this memory is still undefined behavior, but
is much less likely to be caught by the operating system, so usually
the result is that nothing "unexpected" will happen at the very
momement of the read or write operation, but it is quite likely
that some data needed later gets destroyed, resulting in a "crash"
later (when the boss looks over your shoulder).

The following program invokes undefined behavior:

/* undef.c */
#include <stdio.h>

int main(void)
{
int i;
int array[2];

for (i = 0; i < 4; ++i) {
printf("i = %d\n", i);
array = 0;
}

printf("The end!\n");
return 0;
}

It writes a zero to element 0-3 of 'array' which only has elements
0-1. The output from my system is (it could be something else on your):

% gcc undef.c -o undef
% ./undef
i = 0
i = 1
i = 2
i = 3
i = 1
i = 2
i = 3
i = 1
i = 2
i = 3

Oops its looping. The entire logic of my program changed as a result
of writing past the end of an array. In this case array[3] happened
to be the same thing as i.

Below is an example of how the mapped memory of a process might be
organized.

+-----------------------------------+
| |
| Program stack |
| (function return addresses, |
| local variables and |
| function arguments |
| |
+-----------------------------------+
| |
| |
| Unused |
| |
| |
+-----------------------------------+
| |
| Free store |
| (also known as "heap") |
| This is where the malloc family |
| of function gets its memory. |
| |
| |
+-----------------------------------+
| |
| Executable code |
| main(), printf()... |
| |
+-----------------------------------+
| |
| Initialized data |
| (globals, local static, |
| string literals...) |
| |
+-----------------------------------+

The C standard says nothing of how memory should be organized,
but the scheme above is very common. The order of the different
sections might change between platforms and operating systems,
and there might be some additional sections, but except for
DS9000 and similar platform the above is in priniple true.

The impact of this is that it is pretty easy to predict what will
happen when a program uses memory illegally:

Writing out of bounds of a global array will modify another
global variable. Writing data to a function pointer will immediatly
crash the program (os protection of read-only memory). Writing
out of bounds of a dynamically allocated array will either corrupt
the free store or change the value of another dynamically allocated
variable. And finally writing out of bounds of a local variable
will either change the value of another local variable or corrupt
the call stack.

The worst error (in the meaning most difficult to debug) of these
errors, according to my experience, is corrupting the free store.
The reason is that the system (malloc family of functions) stores
book-keeping data (like the size of allocated arrays, and location
of freed arrays) together with the dynamically allocated variables,
and corrupting such data might lead to a program crash much much
much later in the program execution, in a totally unrelated part
of the program.

Hope the above rambling was of some help for someone, and not
considered too off topic by the rest...

/Niklas Norrthon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top