2

I'm trying to get to grips with malloc, and so far I'm mostly getting unexpected results when testing and playing around with it.

int main(int argc, char** argv)
{
    int size = 10;
    int *A;
    A = (int *)malloc(size * sizeof(int));
    for (int i = 0; i < 10000; i++)
    {
        A[i] = i;
    }
    for (int i = 0; i < 10000; i++)
    {
        printf("%d) %d\n", i, A[i]);
    }
}

With this example code above for example, the code runs without an error. Even though I only allocated A to hold 10 * int, so I expected the loop to only run 10 times before hitting an error. If I increment the loop to about 30-40k instead, it then hits a segmentation error. However if I increase my size to the loop amount, it would always work like expected. So I know how to avoid the error.. kinda, I was just hoping someone might be kind enough to explain why this is.

Edit: Turned out I didn't appreciate that C doesn't detect out of bounds, I've been looked after way too much by Java and C++. I had undefined behavior and now know it's my job to prevent them. Thanks for everyone that replied.

dbush
  • 205,898
  • 23
  • 218
  • 273
AspiringNewbie
  • 113
  • 1
  • 7
  • Do not cast `malloc()` and generally `void *`, it's too verbose and thus frowned upon – Iharob Al Asimi Jan 09 '19 at 16:35
  • 2
    overflowing a memory buffer is undefined behavior, which means you don't know what will happen. `malloc` doesn't have to return _exactly_ the amount of memory you request. It returns _at least_ as much memory as you request, or nothing. – yano Jan 09 '19 at 16:36
  • It doesn't give you more memory. Accessing memory that does not belong to you is _undefined behaviour_ (google that term). – Jabberwocky Jan 09 '19 at 16:36
  • You have **undefined behavior**. You should be [very scared](https://stackoverflow.com/a/46526702/841108) – Basile Starynkevitch Jan 09 '19 at 16:36
  • There must be a dupe of this. – Jabberwocky Jan 09 '19 at 16:36
  • @BasileStarynkevitch We need a canonical "my program is letting me do UB" Q&A to close duplicates. – Jonathon Reinhart Jan 09 '19 at 16:37
  • 2
    Sorry for the people who felt this was a duplicate. I didn't even know what undefined behavior was and that is what my program was experiencing, so it's difficult to search for that term before making a thread like this. Believe me I googled a lot before I asked here, and checked other stackoverflow posts. My apologies anyway and thank you for everyone who replied so quickly, you've helped more than you realize :) – AspiringNewbie Jan 09 '19 at 16:51
  • "*... explain why this is.*": Undefined behaviour is undefined. – alk Jan 09 '19 at 17:12
  • OT: If your compiler told you to cast `malloc()` it's not a C compiler, but most likely a C++ compiler. If you you want to do C, use a C compiler, not a C++ compiler. – alk Jan 09 '19 at 17:15
  • "I expected the loop to only run 10 times before hitting an error." is like diving attempting to drive faster than the speed limit and expecting a speeding ticket. C expect coders to follow the rules and leaves much policing to the coder. C is not specified to detect the error. Welcome to programming without training wheels. – chux - Reinstate Monica Jan 09 '19 at 17:25
  • @chux It was pretty ignorant of me to not know that C doesn't handle out of bounds exceptions etc, for some reason I thought it did. I'm still very new to C, and didn't realize how much Java and C++ were babysitting me until now. Trust me I feel stupid for not realizing but I've learnt my lesson with this feedback. I can't apologise for trying to playwith malloc to try to better understand it though.. – AspiringNewbie Jan 09 '19 at 17:31
  • 2
    There's absolutely nothing to apologize or to feel stupid for. You've learned a difference between C and the languages you have come from and that's great – Ingo Leonhardt Jan 09 '19 at 18:21
  • 1
    If one of these answers helped you, you should [accept it](https://stackoverflow.com/help/accepted-answer). – dbush Jan 09 '19 at 20:50

3 Answers3

9

C isn't required to perform any bounds checking on array access. It can allow you read/write past that without any warning or error.

You're invoking undefined behavior by reading and writing past the end of allocated memory. This means the behavior of your program can't be predicted. It could crash, it could output strange results, or it could (as in your case) appear to work properly.

Just because the program can crash doesn't mean it will.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Thank you for the answer, I'm quite new too C and well programming generally. I didn't know the program would still run even when I thought it shouldn't. So essentially as long as be careful to never go past the memory I allocate to it with some kind of check I should be fine using it? – AspiringNewbie Jan 09 '19 at 16:42
  • 2
    @ChrisRafferty Correct. You need to keep track of the size yourself and ensure you don't do something you shouldn't. – dbush Jan 09 '19 at 16:43
  • 1
    A subtle point to this good answer: C does not _require_ bounds checking. A C compiler could emit code to perform such checks on array access - or not. – chux - Reinstate Monica Jan 09 '19 at 17:28
4

The codes runs without an error, but it is still wrong. You just do not notice it. Your loop runs out of the allocated area, but the system remains unaware of that fact until you run out of a much larger area your program can potentially access.

Picture it this way:

<UNAVAILABLE><other data>1234567890<other data><UNAVAILABLE>

Your 10 ints are in the middle of other data, which you can read and even write - to very unpleasant effects. C is not holding your hand here - only once you go out of the total available memory, the program will crash, not before.

Norwæ
  • 1,575
  • 8
  • 18
  • Thank you for your time replying. I didn't actually know the program can run when it shouldn't be. I was just expected some kind of out of bounds error and then it to crash. Guess i learnt something valuable, thanks again! – AspiringNewbie Jan 09 '19 at 16:47
1

Undefined behavior doesn't mean "guaranteed segmentation fault"; it may work in some cases.

There is no way of knowing how far beyond an array's bounds you can go before you finally crash; even dereferencing one element beyond a boundary is undefined behavior.

Also: if malloc succeeds, it will allocate at least as much space as you requested, possibly more.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
  • Thank you for clearing that up like some of the other users before you. The main thing is that it that at least gives me as much as I requested, and then I set up checks to make sure it never goes over. I just didn't understand the fact the program would run when past what was allocated, but now I know, thanks again. – AspiringNewbie Jan 09 '19 at 16:49