2

In the following code I want to catch either asynchronous and synchronous exceptions by use of c++ catch (...) according Microsoft Page descriptions about Exception Handling Model.

Also I set the "Exception Handling Model" up to Yes with SEH Exceptions (/EHa) value.

I tested the code with the following states respectively :

  • When I copy a string in an unallocated char* (char *c;), then i can catch its exception in catch (...) section. (However I know this is an undefined behavior!)

  • But when I copy a string in an array of characters (the string is larger than the array size), then I can't catch any exception !!

  • In the 2nd state, while debugging I got Access Violation error. but why cannot catch its exception like the 1st state ??

  • I tried another solutions as mentioned in :

    Catching access violation exceptions?

But also The problem persists.


This is my code (I tested strcpy() either on an unallocated char* and on an array of characters):

int main()
{
    char c[3] = { 0 };        // Cannot catch any exception
    //char *c;                // Can catch exception

    try
    {
        strcpy(c, "abcdefghijklmnopqrstuvwxyz1234567890");
    }
    catch (...)
    {
        cout << "Undefined behavior!" << endl;
    }

    return 0;
}
Community
  • 1
  • 1
  • 2
    Both of them are undefined behavior, and undefined behavior doesn't have any guaranteed behavior that you can count on. As such, you can't count on your `try`/`catch` to catch an exception caused by the UB, because there might not be any exception. The way to go is to simply not have any undefined behavior. – Blaze Mar 26 '19 at 07:16
  • 1
    Exceptions are happening on prefeclared things. What's happening here, is UB, no requirement on diagnostics there. And from "metal" side of view, going out of array bounds won't necessary cause access violation as long as writing would happen to a memory where process allowed to write. – Swift - Friday Pie Mar 26 '19 at 07:18
  • @Swift-FridayPie why can i get exception when i use strcpy for an unallocated char*? and in the second state i cant get any exception? – BattleTested_закалённый в бою Mar 26 '19 at 07:31
  • Second case: You have a uninitialized pointer, which would be de-referenced by `strcpy`, which is UB. In reality the value of pointer is undetermined, some random value which never was returned by new expression or by `malloc()`. Writing by using that value as an address result in process accessing memory that wasn't assigned to process or wasn't writeable. Hence it results in segmentation fault or similar state. – Swift - Friday Pie Mar 26 '19 at 08:11
  • First case. You created storage to contain three characters. But likely that storage would be allocated in area where other variables may be. E.g. some realization puts them in stack. Writing larger amount of character may not result in page fault, page shortage, segmentation fault. If you had declared other variables there, their content would become undetermined, being overwritten. What actually happens is not described by C++ standard and declared as UB per documentation on `strcpy`. – Swift - Friday Pie Mar 26 '19 at 08:11
  • 1
    First case much more dangerous than second, for program, in terms that program wouldn't continue to run. But not always: in big system random value of pointer might be actually one of previous value and be pointing to some used area of memory. Writing there results in catastrophic damage to data or program flow. First case may result in obfuscated security risks. E.g. there are two buffers and exceeding one, you write to second one and , in result, you may send data which wasn't intended to be send. Recent ssh's heart-beat flaw was of this kind of UBs. – Swift - Friday Pie Mar 26 '19 at 08:26
  • @Swift-FridayPie what if when i define that pointer like : `char *c = 0`??? I mean pointing to `0`. – BattleTested_закалённый в бою Mar 26 '19 at 08:28
  • @Swift-FridayPie what if when i define that pointer like : char *c = 0??? I mean pointing to 0. is it still have a random value??? – BattleTested_закалённый в бою Mar 26 '19 at 08:46
  • @BattleTested if you explicitly initialize it to 0, you explicitly cause an UB by accessing an object which doesn't exist. Now, on most system that would cause umasked intterupt\signal which would end the process (but this isn't defined by standard). `char *c =0 *c =0;` followed by infinite cycle in a noreturn function is a somewhat common method to crash your program. – Swift - Friday Pie Mar 27 '19 at 07:08

1 Answers1

0

Access violation does not require an exception to be raised.

What you have here is undefined behavior. As per documentation of strcpy

The behavior is undefined if the dest array is not large enough. The behavior is undefined if the strings overlap.

P.W
  • 26,289
  • 6
  • 39
  • 76
  • 1
    Sure, but that's not really the question. They say that they are getting an access violation, and it's not being caught. A simple modification to most likely force a memory protection fault would be `strcpy(NULL, "die");` – paddy Mar 26 '19 at 07:17
  • 1
    @paddy: Does access violation result in an exception? I don't think so. If it does, it will be caught. The implementation is not required to raise an exception for access violations. And that is what this answer says. – P.W Mar 26 '19 at 07:19
  • No, it doesn't. The answer just muddies those waters because you mention it in passing in a way that collapses it with your summary of the `strcpy` documentation, rather than a separate fact completely unrelated to `strcpy` or undefined behavior. – paddy Mar 26 '19 at 07:23
  • @paddy why can i get exception when i use `strcpy` for an unallocated `char*`? and in the second state i cant get any exception? – BattleTested_закалённый в бою Mar 26 '19 at 07:36
  • @paddy. Most implementation do not catch that. on POSIX system you can catch some signals by using run-time handler for signals, because OS supposed to send certain signal to process, but for this case the signal is not inteceptable and results in process shut down. Before any other logic within may prevent it. That's a wise design, because otherwise faulty process may cause damage to multi-user environment or even make OS inoperable (enough to reach state where it would be able to write into a file mapped to memory). – Swift - Friday Pie Mar 26 '19 at 08:16
  • @BattleTested read the answers to the question marked as duplicate – paddy Mar 26 '19 at 08:17
  • @BattleTested and my comment which makes parallel between them and your case – Swift - Friday Pie Mar 26 '19 at 08:18
  • @Swift-FridayPie I wasn't arguing that access violation should raise an exception. I was pointing out that this information was hidden or otherwise not evident in an answer that was (and still is) largely addressing the aspect of undefined behavior. – paddy Mar 26 '19 at 08:20
  • @paddy: It's unfortunate that you can't see what is mentioned in the answer (especially after the edit). Have a good day! – P.W Mar 26 '19 at 08:29
  • No, I can see it. The issue was simply that the main thrust of the question is about the OP wanting to know why they can't catch an access violation. To just address that in a short sentence without reference and then go on to reference other distantly-related detail, in my opinion, wasn't a satisfactory answer to the question. It's all moot in any case, since it was since closed as a duplicate and there's some more in-depth information over there. Cheers :) – paddy Mar 26 '19 at 08:36