40

I had this argument with some people saying that C out-of-bound pointers cause undefined behavior even if they're not being dereferenced. example:

int a;
int *p = &a;
p = p - 1;

the third line here will cause undefined behavior even if p is never dereferenced (*p is never used).

In my opinion, it sounds illogical that C would check if a pointer is out-of-bound without the pointer being used (it's like someone would inspect people on the street to see if they're carrying guns in case they enter his house. Where the ideal thing to do is to inspect people when they're about to enter the house). I think if C checks for that then a lot of runtime overhead will occur.

Plus, if C really check for OOB pointers then why this won't cause UB:

int *p; // uninitialized thus pointing to a random adress

in this case why nothing happen even if the chance of p pointing to an OOB adress is high.

ADD:

int a;
int *p = &a;
p = p - 1;

say &a is 1000. Will the value of p after evaluating the third line be:

  • 996 but still undefined behavior because p could be dereferenced somewhere else and cause the real problem.
  • undefined value and that's the undefined behavior.

because I think that "the third line was called to be of undefined behavior" in the first place was because of the potential future use of that OOB pointer (dereferencing) and people, over time, took it as an undefined behavior in it's own. Now, is the value of p will be 100% 996 and that still undefined behavior or its value will be undefined?

Dan
  • 10,303
  • 5
  • 36
  • 53
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
  • 30
    No; C doesn't check whether pointers are valid or not — period. The o/s memory management system provides some checking, but if the pointer is invalid, your program crashes. – Jonathan Leffler Jan 16 '17 at 00:04
  • That's exactly what i said. It cause problem If `*p` is evaluatued somewhere. – ibrahim mahrir Jan 16 '17 at 00:08
  • 7
    " illogical that C would check if a pointer" --> C is not obligated to check if `p = p - 1` did not cause a problem or not. That is the source of UB. – chux - Reinstate Monica Jan 16 '17 at 00:16
  • 2
    In the 2nd case, although declared, `p` need not exist until used. – chux - Reinstate Monica Jan 16 '17 at 00:17
  • in your uninitialized state, it doesn't really do anything other than create some space for the pointer. In the pointer arithmetic, you could be going out of memory bounds, going below address 0 for example. The standard doesn't want to define what happens with that as it doesn't really matter, hence why it's going to be UB – Keith Nicholas Jan 16 '17 at 00:18
  • 4
    The question in the original argument was not whether C checks the validity of pointers, but whether it is undefined behavior to add a pointer to some array object and an integer, to form a pointer that does not point to the array object. The Standard says that it is undefined behavior to form such a pointer if it points somewhere other than to the array object or one past the end of the object. – ad absurdum Jan 16 '17 at 00:19
  • 37
    "Does C check this?" and "Is this undefined behaviour?" are two very different questions (and usually they have opposite answers!). – user253751 Jan 16 '17 at 00:31
  • 30
    C is a language; it doesn't check anything. A particular implementation of C *may or may not* generate code that checks pointer values for validity. An compiler that generates code that causes a trap on the evaluation of `p - 1` would be conforming; since the behavior is undefined, it can do literally anything it likes. It happens that most implementations don't generate code to perform such checks, because the resulting code would be slower than code without the checks. On the other hand, it's common for compilers to issue warnings for undefined behavior if it can be detected at compile time. – Keith Thompson Jan 16 '17 at 00:32
  • This question gave me a good chuckle. I made a considerable amount of money back in the 1980's selling a source-level debugger called CDB. One of our trade show booth props was a bug-like creature dressed as a mafia hitman. We galled him Bugsy Malone and claimed he was wanted for Malicious Assault on a Global Pointer. BTW: @KeithThompson - Is that *the* Keith Thompson I think it is? If so, Hi! Long time, etc., etc. – Peter Rowell Jan 16 '17 at 02:21
  • @PeterRowell he signs off as "the other Keith" so perhaps it is a 50/50 chance – M.M Jan 16 '17 at 10:22
  • 2
    some hardware can throw a hardware exception if a pointer register holds a value that is outside any range assigned by the MMU . If `p` happens to be the start of a virtual address space then `p-1` may cause this exception – M.M Jan 16 '17 at 10:23
  • 1
    @ibrahimmahrir No, that’s *not* what you said, quite the opposite. And since the expression causes undefined behaviour, the program may crash (or do whatever) even if `*p` is never evaluated anywhere. – Konrad Rudolph Jan 16 '17 at 13:22
  • 1
    Trouble is, even though most modern hardware will not act up on the pointer assignment, your compiler may remove other code when it can prove undefined behavior. As such, any code after `p = p - 1;` might be removed entirely. That is the real danger. – cmaster - reinstate monica Jan 16 '17 at 14:17
  • Your addition to your question highlights that you're still confused about what undefined behavior means. I suggest you go read some other definitions and explanations of it. One place to start might be [this other question](http://stackoverflow.com/q/2397984). A hint: your added question sounds almost like "if this is unpredictable, then what will happen?" – Dan Getz Jan 16 '17 at 14:41
  • "Now, is the value of p will be 100% 996 and that still undefined behavior or its value will be undefined?" --> The calculation that did `1000-4` to hopefully generate `996` may fail a bounds check and cause a fault as values below 1000 were not allocated for this type - this check is not part of the instructions and is not code overhead. This type of checking halts bad or nefarious code. From C's point-of-view, it is UB. – chux - Reinstate Monica Jan 17 '17 at 06:13
  • As @KeithThompson pointed out, there is no defined behavior for undefined behavior. One compiler may allow the operation, and any resultant runtime consequence which may occur. Another compiler may detect the undefined nature of the operation and produce diagnostic warnings at compile time. "Undefined behavior" cannot be equated to any defined exception like "out of bounds" or sigsegv. Whether or not anything untoward happens when the code behaves in an undefined way is coincidental. The point is the language has no definition for what is supposed to happen. – CuriousRabbit Jan 17 '17 at 19:02

9 Answers9

66

C does not check if a pointer is out of bounds. But the underlying hardware might behave in strange ways when an address is computed that falls outside the object boundaries, pointing just after the end of an object being an exception. The C Standard explicitly describes this as causing undefined behavior.

For most current environments, the above code does not pose a problem, but similar situations could cause segmentation faults in x86 16-bit protected mode, some 25 years ago.

In the language of the Standard, such a value could be a trap value, something that cannot be manipulated without invoking undefined behavior.

The pertinent section of the C11 Standard is:

6.5.6 Additive operators

  1. When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. [...] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.

A similar example of undefined behavior is this:

char *p;
char *q = p;

Merely loading the value of uninitialized pointer p invokes undefined behavior, even if it is never dereferenced.

EDIT: it is a moot point trying to argue about this. The Standard says computing such an address invokes undefined behavior, so it does. The fact that some implementations might just compute some value and store it or not is irrelevant. Do not rely on any assumptions regarding undefined behavior: the compiler might take advantage of its inherently unpredictable nature to perform optimizations that you cannot imagine.

For example this loop:

for (int i = 1; i != 0; i++) {
    ...
}

might compile to an infinite loop without any test at all: i++ invokes undefined behavior if i is INT_MAX, so the compiler's analysis is this:

  • initial value of i is > 0.
  • for any positive value of i < INT_MAX, i++ is still > 0
  • for i = INT_MAX, i++ invokes undefined behavior, so we can assume i > 0 because we can assume anything we please.

Therefore i is always > 0 and the test code can be removed.

Community
  • 1
  • 1
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 2
    "_...pointing just after the end of an object being an exception._" -- Is this true for any object or just for array objects? So, Is `int a = 3, *p = &a + 1;` valid? – Spikatrix Jan 16 '17 at 00:58
  • 6
    @CoolGuy Yes, it applies to any object. The immediate previous paragraph in the Standard says: *"For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type."* So for the purposes of this, non-array objects are array objects with length 1. – Theodoros Chatzigiannakis Jan 16 '17 at 01:22
  • 8
    Not just "the underlying hardware" that "might behave in strange ways". Regardless of the hardware, the compiler is free to generate code that might behave inconsistently when UB has been invoked. For instance, in OP's example, `p>=&a` might evaluate true in some places and false in others, or `p==&b` (for some other variable `b`) might evaluate true in some places (where the compiler doesn't see the origin of `p`) and false in others (where the compiler sees that `p` is based on `&a` and thus could never be equal to the address of another object `b`). – R.. GitHub STOP HELPING ICE Jan 16 '17 at 02:32
  • @R..: I agree completely. Your examples are perfect illustrations for the latter part of the answer. Feel free to edit them in. – chqrlie Jan 16 '17 at 02:58
  • Possible cause of confusion could be people saying "invokes UB". UB is not something that is invoked. It is something to be had. I have a behavior, you have a behavior, a program has an undefined behavior. – Shahbaz Jan 16 '17 at 04:24
  • @Shahbaz: I agree the idiom is misleading. The Standard merely says *otherwise, the behavior is undefined.* – chqrlie Jan 16 '17 at 04:32
  • 6
    Well, because the behavior is undefined, a conforming implementation is allowed to check whether a pointer is out-of-bounds and crash with a runtime error. It’s also allowed to do that on Mondays, Wednesdays and Fridays; to treat the code as correct and let it run on Tuesdays and Thursdays; and on the weekends, to `exec` `nethack`. One compiler, just to make the point that it was never going to support a nonstandard extension, really did run a roguelike game whenever it encountered a line starting with `#pragma`. It’s allowed to do *anything*. – Davislor Jan 16 '17 at 06:21
  • You might want to extend your infinite loop example: Given `int a; int*p = &a; if (foo == nullptr) p--; else foo->call(p);` the compiler can deduce that foo is never null and eliminate the test. – Martin Bonner supports Monica Jan 16 '17 at 09:56
  • @Davislor I was very interested to read more about the cheeky compiler's roguelike game, but a quick search didn't turn up anything. Do you have a link? – Bear Jan 16 '17 at 14:06
  • `> would cause segmentation faults in x86 16-bit protected mode` No, decreasing a pointer in 16-bit protected mode will at most wrap-around the offset to `0xffff`, and if you don't dereference the resulting pointer, you're safe. And decreasing selector doesn't make sense anyway, since it's not related to physical address directly as it is in real mode. – Ruslan Jan 16 '17 at 18:37
  • 1
    @Bear It was a very old version of GCC. Here’s a Usenet post from 1990 talking about it: https://groups.google.com/forum/#!msg/comp.lang.c/wU-kjw7XrRQ/fbHMFc-rE4EJ – Davislor Jan 16 '17 at 22:43
  • `char *p; char *q = p;` is an example of undefined behavior, is it? @chqrlie. – haccks Jan 17 '17 at 10:17
  • @haccks: most definitely so. – chqrlie Jan 17 '17 at 13:48
  • @Ruslan: decreasing the selector was done in protected mode too for huge pointers. They actually used a relocation trick to adjust the selectors differently in real and protected mode. Huge memory blocks (spanning multiple 64 KB blocks were mapped into successive selectors. Computing the selector for an unallocated block and loading that into a segment register (via the `LES` instruction) could produce a segmentation fault. – chqrlie Jan 17 '17 at 13:52
  • In what systems did C compiler do such tricks with selectors? It must have been confident that successive blocks mapped to successive selectors by the OS, or was it incorporating a DOS extender into the (DOS) program? – Ruslan Jan 17 '17 at 15:56
  • all 16-bit protected mode Windows and 16-bit real mode DOS compilers used to do this in the early '90s: Microsoft C, Borland C, Zortech-C, Watcom C, Concurrent C, Wizard C, Metaware High-C, all did that. – chqrlie Jan 17 '17 at 16:03
22

Indeed, the behaviour of a C program is undefined if it attempts to compute a value through pointer arithmetic that does not result to a pointer to an element, or one past the end of, the same array element. From C11 6.5.6/8:

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

(For the purpose of this description, the address of an object of a type T maybe treated as the address of the first element of an array T[1].)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I was one of the parties involved in the aforementioned argument, and this is exactly what I cited. – ad absurdum Jan 16 '17 at 00:13
  • One of the few [questions I've asked on SO](https://stackoverflow.com/questions/30512669/does-applying-post-decrement-on-a-pointer-already-addressing-the-base-of-an-arra) drew similar conclusion. It is indeed UB. – WhozCraig Jan 16 '17 at 00:18
  • 1
    @WhozCraig-- the first time I bumped into this issue, I was iterating over a string from back to front, just like the code in the [question you linked to](https://stackoverflow.com/questions/30512669/does-applying-post-decrement-on-a-pointer-already-addressing-the-base-of-an-arra). The code worked, but I was uneasy about going one-off of the front of the array with the pointer. Consulting 6.5.6/8 convinced me not to play with this. – ad absurdum Jan 16 '17 at 00:42
  • 2
    @DavidBowling: Careful with liberal interpretation of what "working" means! – Kerrek SB Jan 16 '17 at 00:45
  • @KerrekSB-- Right! I should have said that it _"worked"_. Needless (?) to say, I changed the code to avoid the UB. – ad absurdum Jan 16 '17 at 00:47
15

To clarify, "Undefined Behavior" means that the outcome of the code in question is not defined in the standards governing the language. The actual outcome depends on the way in which the compiler is implemented, and can range from nothing at all to a complete crash and everything in between.

The standards do not specify that any range checking of pointers should occur. But in relation to your specific example, this is what they do say:

When an expression that has integer type is added to or subtracted from a pointer ... If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.

The above quote is from C99 §6.5.6 Para 8 (the newest version I have on hand).

Note that the above also applies to non-array pointers, since in the previous clause it says:

For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

So, if you perform pointer arithmetic, and the result is either within bounds or points to one past the end of the object, then you will get a valid result, otherwise you get undefined behavior. That behaivour might be that you end up with a stray pointer, but it might be something else.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
harmic
  • 28,606
  • 5
  • 67
  • 91
  • [N1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) is the latest publicly available draft of the current C11 standard. It's good enough for almost all purposes. It was published not long before the official standard, and the differences are minor. – Keith Thompson Jan 16 '17 at 00:30
7

Yes, it is undefined behavior even if the pointer is not dereferenced.

C only allows pointers to point only one element past array bounds.

Community
  • 1
  • 1
Kornel
  • 97,764
  • 37
  • 219
  • 309
4

When specifications say something is undefined, that can be quite confusing.

It means, in that circumstance, the implementation of the specification is free to do whatever it wants. In some cases, it will do something that appears, intuitively, correct. In other cases it won't.

For address-boundary specs, I know my intuition comes from my assumptions about a flat uniform memory model. But there are other memory models.

The word "undefined" never appears in a completed spec unintentionally. Standards committees usually decide to use the word when they know different implementations of the standard need to do different things. In many cases the reason for the different things is performance. So: the appearance of the word in the spec is a red flag warning about that to us mere mortals, users of the spec, that our intuition may be wrong.

This kind of "whatever it wants" specification famously annoyed rms a few years back. So, he made some versions of his Gnu Compiler Collection (gcc) try to play a computer game when it encountered something undefined.

IBM used the word unpredictable in their specifications back in the 360 / 370 days. That's a better word. It makes the outcome sound more random and more dangerous. Within the scope of "unpredictable" behavior lie such problematic outcomes as "halt and catch fire."

Here's the thing, though. "Random" is a bad way to describe this kind of unpredictable behavior, because "random" implies the system may do something different each time it encounters the problem. If it does something different every time, you have a chance of catching the problem in test. In the world of "undefined" / "unpredictable" behavior the system does the same thing every time, until it doesn't. And, you know the time it doesn't will be years after you think you've finished testing your stuff.

So, when the spec says something is undefined, don't do that thing. Unless you're a friend of Murphy. OK?

O. Jones
  • 103,626
  • 17
  • 118
  • 172
4

"Undefined behaviour" means "anything can happen". Common values of "anything" are "nothing bad happens at all" and "your code crashes". Other common values of "anything" are "bad things happen when you turn optimisation on", or "bad things happen when you don't run the code in development but a customer is running it", and still other values are "your code does something unexpected" and "your code does something that it shouldn't be able to do".

So if you say "it sounds illogical that C would check if a pointer is out-of-bound without the pointer being used", you are in very, very, very dangerous territory. Take this code:

int a = 0;
int b [2] = { 1, 2 };
int* p = &a; p - 1;
printf ("%d\n", *p);

The compiler can assume that there is no undefined behaviour. p - 1 was evaluated. The compiler concludes (legally) that either p = &a [1], p = &b [1] or p = &b [2], since in all other cases there is undefined behaviour either when evaluating p or when evaluating p-1. The compiler then assumes that *p is not undefined behaviour, so it concludes (legally) that p = &b [1] and prints the value 2. You didn't expect that, did you?

That's legal, and it happens. So the lesson is: Do NOT invoke undefined behaviour.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
4

Some platforms treat pointers as integers, and process pointer arithmetic in the same fashion as integer arithmetic, but with certain values scaled up or down according to the sizes of objects. On such platforms, this will effectively define a "natural" result of all pointer arithmetic operations except subtraction of pointers whose difference is not a multiple of the size of the pointer's target type.

Other platforms may represent pointers in other ways, and addition or subtraction of certain combinations of pointers may cause unpredictable results.

The authors of the C Standard didn't want to show favoritism toward either kind of platform, so it imposes no requirements on what may happen if pointers are manipulated in ways that would cause problems on some platforms. Before the C Standard, and for quite a few years afterward, programmers could reasonably expect that general-purpose implementations for platforms which treated pointer arithmetic like scaled integer arithmetic would, themselves, treat pointer arithmetic likewise, but implementations for platforms that treated pointer arithmetic differently would likely treat it differently themselves.

In the last decade or so, however, in pursuit of "optimization", compiler writers have decided to throw the Principle of Least Astonishment out the window. Even in cases where a programmer would know what the effect of certain pointer operations would be given a platform's natural pointer representations, there's no guarantee that compilers will generate code that behaves the way the natural pointer representations would behave. The fact that the Standard says behavior is undefined is interpreted as an invitation for compilers to impose "optimizations" that force programmers to write code that is slower and clunkier than it would need to be on implementations that simply behave in a fashion consistent with the document behaviors of the underlying environment (one of the three treatments that the authors of the C89 explicitly noted as being commonplace).

Thus, unless one knows that one is using a compiler which doesn't have any wacky "optimizations" enabled, the fact that an intermediate step in a sequence of pointer computations invokes Undefined Behavior makes it impossible to reason at all about it, no matter how strongly common sense would imply that a quality implementations for a particular platform should behave a particular way.

supercat
  • 77,689
  • 9
  • 166
  • 211
3

The part of the question relating to undefined behavior is very clear, the answer is "Well, yes, certainly it is undefined behavior".

I will interprete the wording "Does C check..." as the following two:

  1. Does the C compiler check...?
  2. Does my compiled program check...?

(C itself is a language specification, it doesn't check, or do, anything)

The answer to the first question is: Yes, but not reliably, and not in the way you wish. Modern compilers are quite smart, sometimes smarter than you'd like. The compiler will, in some cases, be able to diagnose your illegitimate use of pointers. Since this per definition invokes undefined behavior and the language therefore no longer requires the compiler to do anything in particular, the compiler will often optimize in an unpredictable way. This may result in code that is much different from what you originally intended. Do not be surprised if an entire scope or even the complete function gets dead-stripped. This is true for many undesirable "surprise optimizations" in relation to undefined behavior.
Obligatory read: What Every C Programmer Should Know About Undefined Behavior.

The Answer to the second question is: No, except if you use a compiler which supports bounds checks and if you compile with runtime bounds checks enabled, which implies a quite non-trivial runtime overhead.
In practice, this means that if your program "survived" the compiler optimizing out undefined behavior, then it will just stubbornly do what you told it to do, with unpredictable results -- usually either garbage values being read, or your program causing a segmentation fault.

Damon
  • 67,688
  • 20
  • 135
  • 185
0

But what is undefined behavior? That simply means no one is willing to say what will happen.

I'm an old mainframe dog from years back, and I like IBM's phrase for the same thing: results are unpredictable.

BTW: I like the idea of NOT checking array bounds. For example, if I have a pointer into a string, and I want to see what's just before the byte being pointed to, I can use:

pointer[-1]

to look at it.

Adriaan
  • 17,741
  • 7
  • 42
  • 75
Jennifer
  • 153
  • 6
  • 9
    **This is extremely bad practice!** Because `results are unpredictable`, even in the most trivial program, it's not guaranteed that attempting to access `pointer[-1]` won't summon nasal demons during some execution of the program. – Jules Jan 16 '17 at 09:44
  • 1
    Don't understand the down-votes. "If you do this, you can't predict what will happen". – Martin Bonner supports Monica Jan 16 '17 at 09:52
  • 2
    `pointer[-1]` example unfortunately has room for misinterpretation. Is `pointer` initialized with `pointer = &string[0]` vs `pointer = &string[5]`. And this is reflected in the comments to this answer. – user694733 Jan 16 '17 at 10:02
  • 5
    _"if I have a pointer into a string, and I want to see what's just before the byte being pointed to, I can use"_ Nope. – Lightness Races in Orbit Jan 16 '17 at 10:11
  • @MartinBonner the answer reads as if OP thinks that `pointer[-1]`, when pointer points into a string but not the first character, would cause an error if there were array bounds checking. When in fact it would not. – M.M Jan 16 '17 at 10:19
  • 5
    @LightnessRacesinOrbit uh, actually it is fine (assuming pointer does not point to first character of string). `x[-1]` is defined as `*(x-1)` and you can look up the rules for subtraction of integer from pointer. – M.M Jan 16 '17 at 10:21
  • @M.M: "Assuming". I read the answer as meaning `pointer` is a pointer to the first element, and Jennifer wanted to see what was happening "before" the string. Otherwise why mention array bounds. Although to be fair I can see now how one might read it differently. Perhaps Jennifer can clarify? – Lightness Races in Orbit Jan 16 '17 at 11:19
  • Blast: I didn't fully read the "I can use" sentence - that is wrong. It *might* work, but you can't rely on it. – Martin Bonner supports Monica Jan 16 '17 at 11:29
  • 2
    If nothing else this answer is still dangerous as currently written, if others may read it the same way I did and take it to mean they can perform pointer magic outside of arrays. – Lightness Races in Orbit Jan 16 '17 at 12:02
  • 1
    No you can't. *(p - 1) may, or may not, point to a valid address depending on factors not currently specified, so since the results can not be predicted with the information at hand, you have a perfect example of "Undefined Behavior". – Paul Smith Jan 16 '17 at 13:14
  • Even if the pointer DOES point to the beginning of the string, pointer[-1] will STILL show you what's just in front of the pointed-to element. Whether or not that data is meaningful is up to you. C will NOT validate the pointer or what it deferences, so it will always work as I described without throwing an unwanted error. And its true, there are "gotchas" when adding or subtracting or using subscripts: the integer will be multiplied by the width of the items in the array (I got caught on this several times) but if it points to string, each char has length 1 so this problem does not apply. – Jennifer Jan 17 '17 at 15:49
  • To clarify: all I know is that pointer points somewhere into a string. It is not necessarily the first position or a non-first position. Example: `char* pointer; pointer = strchr(string, '_'); printf("%c", pointer[-1]);` Potentially nonsense, but it could be useful sometimes. – Jennifer Jan 17 '17 at 15:59
  • In C, what you would get is *whatever is in the byte prior to what* pointer *is pointing to,* even if it is pointing to the first byte of a string, to a random address in memory, or wherever. The only exception is if doing so would cause a segmentation fault. – Jennifer Mar 06 '17 at 09:38