By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,173 Members | 1,079 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,173 IT Pros & Developers. It's quick & easy.

Getting Segmentation Fault, selectively, on memory overwrite.

P: n/a
Hello Everyone,

I am seeing a certain behaviour which I find strange, and am curious to get an
explanation to it. I have the following program.

#include <iostream>
#include <cstdlib>

using namespace std;

int main(int argc, char ** argv) {
if(argc<2) {
return -1;
}

int value = atoi(argv[1]);
char * arr = new char[value];
// No segmentation fault unless next is an array.
char * next = new char[value];

int i = 0;
for(i=0; i<value; i++) {
arr[i] = 'a';
next[i] = 'a';
}
// NOTE: I am adding a char beyond the array boundary
arr[i]='\0';
next[i]='\0';
// This causes a segmentation fault
delete [] arr;
}

I compiled this with 3.2.2 on Red Hat Linux 9 on an Intel i686. When I run the
program, it gives me a Segmentation fault only when the array size is an odd
multiple of 4. My guess is it has something to do with word alignment. But, what
exactly is happening here?

Thanks for your help,
Vishal Grover
Developer
Trilogy Software Inc.
Jul 19 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Vishal Grover wrote:
Hello Everyone,

I am seeing a certain behaviour which I find strange, and am curious to get an
explanation to it. I have the following program.

#include <iostream>
#include <cstdlib>

using namespace std;

int main(int argc, char ** argv) {
if(argc<2) {
return -1;
}

int value = atoi(argv[1]);
char * arr = new char[value];
// No segmentation fault unless next is an array.
char * next = new char[value];

int i = 0;
for(i=0; i<value; i++) {
arr[i] = 'a';
next[i] = 'a';
}
// NOTE: I am adding a char beyond the array boundary
If you know this, why are you surprised that the program doesn't behave
well?
arr[i]='\0';
next[i]='\0';
// This causes a segmentation fault
delete [] arr;
}

I compiled this with 3.2.2 on Red Hat Linux 9 on an Intel i686. When I run the
program, it gives me a Segmentation fault only when the array size is an odd
multiple of 4.
That's perfectly acceptable behavior for a program with undefined behavior.
My guess is it has something to do with word alignment. But, what
exactly is happening here?
Undefined behavior.

Thanks for your help,
Vishal Grover
Developer
Trilogy Software Inc.


I'm considering making a note of this company's name so I can be sure
never to buy software from them... Can you explain *why* you are
intentionally overflowing an array in your code, in order to restore
some of my confidence in the software industry?

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #2

P: n/a

"Vishal Grover" <vi***********@rediffmail.com> wrote in message
news:a6**************************@posting.google.c om...
Hello Everyone,

I am seeing a certain behaviour which I find strange, and am curious to get an explanation to it. I have the following program.

#include <iostream>
#include <cstdlib>

using namespace std;

int main(int argc, char ** argv) {
if(argc<2) {
return -1;
}

int value = atoi(argv[1]);
char * arr = new char[value];
// No segmentation fault unless next is an array.
char * next = new char[value];

int i = 0;
for(i=0; i<value; i++) {
arr[i] = 'a';
next[i] = 'a';
}
// NOTE: I am adding a char beyond the array boundary


But why? You haven't allocated enough space to write another extra
character.
Strings do end with a null character but then you need to allocate space for
that null character
also. I hope you know that.

Taking that into consideration -
char * arr = new char[value + 1];
char * next = new char[value + 1];
should be what would get you the desired result.

HTH,
J.Schafer

Jul 19 '05 #3

P: n/a
Kevin Goodsell
// NOTE: I am adding a char beyond the array boundary
If you know this, why are you surprised that the program doesn't behave
well?


Because, this is a test case which I had written to investigate a bug. I am
not questioning the fact that the program doesn't behave well. My question
is why isn't the behaviour not uniform for each input value.
I compiled this with 3.2.2 on Red Hat Linux 9 on an Intel i686. When I run the
program, it gives me a Segmentation fault only when the array size is an odd
multiple of 4.


That's perfectly acceptable behavior for a program with undefined behavior.


Nowhere have I claimed that the behaviour is not acceptable. I am just looking
for an explanation for the behaviour.
My guess is it has something to do with word alignment. But, what
exactly is happening here?


Undefined behavior.


No machine or compiler, at least the non-quantum ones, has a non-deterministic
behaviour, given perfect knowledge about the system. In case you did not
get the question, I was looking for an insight on how does a popular
compiler like gcc handle undefined behaviour.

I'm considering making a note of this company's name so I can be sure
never to buy software from them... Can you explain *why* you are
intentionally overflowing an array in your code, in order to restore
some of my confidence in the software industry?

Since when is it a bad practice, to write a test case to investigate a potential
bug? You have no right to question the quality of software that
my company makes, based on what I has been given in this mail. If you can't
supply a decent answer, or even if this is not the right place to ask the
question, you have absolutely no right to be rude and make such judgemental
statements.
-Kevin


Thank you very much Kevin, I will not be posting any further questions on this
list

Vishal
Jul 19 '05 #4

P: n/a
Josephine,

I am sorry, if I did not ask the question clearly enough.
// NOTE: I am adding a char beyond the array boundary
But why? You haven't allocated enough space to write another extra
character.
Strings do end with a null character but then you need to allocate space for
that null character
also. I hope you know that.


Yes, I know that and I am overwriting the memory intentionally. I was curious
to know, how would a typical compiler handle such a case. Yes, the behaviour
is indeed undefined according to the language standards in such a case. However,
given a combination of Operating System and Compiler, the behaviour of the
program will have an explanation and I was interested in that explanation.
Maybe, this group is the wrong place to ask this question.
Taking that into consideration -
char * arr = new char[value + 1];
char * next = new char[value + 1];
should be what would get you the desired result.
HTH,
J.Schafer


Thank You,
Vishal
Jul 19 '05 #5

P: n/a
Vishal Grover wrote:
Kevin Goodsell

// NOTE: I am adding a char beyond the array boundary
If you know this, why are you surprised that the program doesn't behave
well?

Because, this is a test case which I had written to investigate a bug. I am
not questioning the fact that the program doesn't behave well. My question
is why isn't the behaviour not uniform for each input value.


There is no C++ language answer for that. You might be able to get an
answer from the compiler vendor. All the C++ standard has to say about
it is that it places no requirements on the program's behavior.

Since when is it a bad practice, to write a test case to investigate a potential
bug? You have no right to question the quality of software that
my company makes, based on what I has been given in this mail. If you can't
supply a decent answer, or even if this is not the right place to ask the
question, you have absolutely no right to be rude and make such judgemental
statements.
You posted blatantly broken code without an explanation or any
indication that you understood that it was broken. What conclusion
should I draw from that? I only asked for an explanation, to hopefully
show my conclusion was wrong.

Thank you very much Kevin, I will not be posting any further questions on this
list


It's a group, not a list. Honestly, I care very little whether you
participate or not. But this is a rather trivial thing to resort to
self-banishment over.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #6

P: n/a
On 9 Sep 2003 21:50:13 -0700, vi***********@rediffmail.com (Vishal Grover) wrote:
I am seeing a certain behaviour which I find strange, and am curious to get an
explanation to it. I have the following program.

#include <iostream>
#include <cstdlib>

using namespace std;

int main(int argc, char ** argv) {
if(argc<2) {
return -1;
}

int value = atoi(argv[1]);
char * arr = new char[value];
// No segmentation fault unless next is an array.
char * next = new char[value];

int i = 0;
for(i=0; i<value; i++) {
arr[i] = 'a';
next[i] = 'a';
}
// NOTE: I am adding a char beyond the array boundary
arr[i]='\0';
next[i]='\0';
// This causes a segmentation fault
delete [] arr;
}

I compiled this with 3.2.2 on Red Hat Linux 9 on an Intel i686. When I run the
program, it gives me a Segmentation fault only when the array size is an odd
multiple of 4. My guess is it has something to do with word alignment. But, what
exactly is happening here?


As others have answered, the only general answer is that you're invoking
undefined behavior, where anything or nothing may happen.

In practice it seems your compiled program is overwriting some allocation
information.

Such information is typically placed right before a dynamically allocated
item. That seems to fit the alignment issue you have noted. It's no
great mystery, but it has nothing to do with C++.

On the topic of C++, in order of appearance in the above code:
* Guideline: don't use atoi, since it has no error checking.
Exception: where you want 0 as result in case of error (add comment).

* Guideline: don't use raw pointers and arrays, use smart pointers and
standard library containers.

* Guideline: avoid using a loop control variable after the loop.

* Guideline: always execute a corresponding 'delete' for each 'new'.

* Guideline: when you rely on the return value 'main' to indicate
failure, express success explicitly by returning EXIT_SUCCESS.
Finally, Word of Advice: don't take technical comments personally and
threaten to "leave this list", as you seem to have done; see e.g.
<url:http://www.winternet.com/~mikelr/flame52.html>.

Jul 19 '05 #7

P: n/a
Vishal Grover wrote:
Josephine,

I am sorry, if I did not ask the question clearly enough.

// NOTE: I am adding a char beyond the array boundary


But why? You haven't allocated enough space to write another extra
character.
Strings do end with a null character but then you need to allocate space for
that null character
also. I hope you know that.

Yes, I know that and I am overwriting the memory intentionally. I was curious
to know, how would a typical compiler handle such a case. Yes, the behaviour
is indeed undefined according to the language standards in such a case. However,
given a combination of Operating System and Compiler, the behaviour of the
program will have an explanation and I was interested in that explanation.
Maybe, this group is the wrong place to ask this question.


You cannot know for sure what will happen when you write past a
dynamically created storage area. You could be attempting to overwrite
basically anything. Maybe the next byte is yours, maybe it isn't.
There is not even a compiler specific answer.

You can know what you will be overwriting if you go past a stack
allocated memory segment. Usually this will be more stack variables and
eventually the return value. This is how buffer overrun exploits occur.

NR

Jul 19 '05 #8

P: n/a

"Vishal Grover" <vi***********@rediffmail.com> wrote in message
news:a6**************************@posting.google.c om...
Josephine,

I am sorry, if I did not ask the question clearly enough.
// NOTE: I am adding a char beyond the array boundary
But why? You haven't allocated enough space to write another extra
character.
Strings do end with a null character but then you need to allocate space for that null character
also. I hope you know that.


Yes, I know that and I am overwriting the memory intentionally. I was

curious to know, how would a typical compiler handle such a case. Yes, the behaviour is indeed undefined according to the language standards in such a case. However, given a combination of Operating System and Compiler, the behaviour of the
program will have an explanation and I was interested in that explanation.
Maybe, this group is the wrong place to ask this question.
Taking that into consideration -
char * arr = new char[value + 1];
char * next = new char[value + 1];
should be what would get you the desired result.
HTH,
J.Schafer

OK may be I can attempt to give you some insight on why your program crashes
sometimes.
Typically most architectures return on a suitable alignment for all types
when dealing with dynamic memory. Thus four bytes are atleast consumed in
practice (even in cases of zero byte allocation). Also implementation(s)
typically use an additional 4-byte word to record allocation sizes, so then
another four bytes are consumed.Such information is typically placed right
before the dynamically allocated item.
When you allocate on multiple of 4 bytes the alignment is proper .Thus when
you try to write past the allocated boundary, you could be attempting to
overwrite basically anything. This may/may not be the same in other cases.
Ofcourse I am just proposing one explanation. An implementation can do it
any way.

HTH,
J.Schafer

Jul 19 '05 #9

P: n/a


Vishal Grover wrote:

Josephine,

I am sorry, if I did not ask the question clearly enough.
// NOTE: I am adding a char beyond the array boundary
But why? You haven't allocated enough space to write another extra
character.
Strings do end with a null character but then you need to allocate space for
that null character
also. I hope you know that.


Yes, I know that and I am overwriting the memory intentionally. I was curious
to know, how would a typical compiler handle such a case.


The compiler doesn't handle anything in this case. What you overwrite,
and if it is vital to the whole system is more or less random and depends
on your exact program text, the state your operating system is in, if there
are other programs running, how low is the operating system on memory, etc.
Add a variable to your function and the symptoms may be different.
Yes, the behaviour
is indeed undefined according to the language standards in such a case. However,
given a combination of Operating System and Compiler, the behaviour of the
program will have an explanation and I was interested in that explanation.
The only way to figure out what really happens in your case is to look
at the assembly output and do a carefull examination and a step through
through the program and hope that the environment your program runs in has
not changed to much, such that the symptoms are different.
Maybe, this group is the wrong place to ask this question.


It is.
This group has no answer for you, because in the context of this group
there doesn't exist an answer, except: undefined behaviour - anything can happen.
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 19 '05 #10

P: n/a
> >I compiled this with 3.2.2 on Red Hat Linux 9 on an Intel i686. When I run the
program, it gives me a Segmentation fault only when the array size is an odd
multiple of 4. My guess is it has something to do with word alignment. But, what
exactly is happening here?
As others have answered, the only general answer is that you're invoking
undefined behavior, where anything or nothing may happen.

In practice it seems your compiled program is overwriting some allocation
information.

Such information is typically placed right before a dynamically allocated
item. That seems to fit the alignment issue you have noted. It's no
great mystery, but it has nothing to do with C++.


This seems a reasonable explanation. Thank you.
On the topic of C++, in order of appearance in the above code:
* Guideline: don't use atoi, since it has no error checking.
Exception: where you want 0 as result in case of error (add comment).

* Guideline: don't use raw pointers and arrays, use smart pointers and
standard library containers.

* Guideline: avoid using a loop control variable after the loop.

* Guideline: always execute a corresponding 'delete' for each 'new'.

* Guideline: when you rely on the return value 'main' to indicate
failure, express success explicitly by returning EXIT_SUCCESS.
Thanks again. Will keep in mind.

Finally, Word of Advice: don't take technical comments personally and
threaten to "leave this list", as you seem to have done; see e.g.
<url:http://www.winternet.com/~mikelr/flame52.html>.


I admit, I am a newbie, and I have learnt a few things today.

Regards
Vishal
Jul 19 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.