funct7
funct7

Reputation: 3601

C `Abort trap: 6` only under certain conditions

I understand Abort trap 6 occurs when you're writing to a part of memory that you don't own, but I realized something interesting while doing K&R exercises.

/* strcat:  copies t to the end of s */
void _strcat(char *s, char *t) {
    while (*s != '\0') { 
        s++;
    }
    while ((*s++ = *t++) != '\0') { }
}

#include <stdio.h>
int main() {
    char s[7] = "hello, ";
    char *t = "world";

    _strcat(s, t);
    printf("%s\n", s);
    return 0;
}

The part of interest is char s[7] = "hello, ".

When the size of array is 7, the exact length of "hello, ", Abort trap 6 is not printed, even though _strcat adds characters beyond the initialized parts of the memory.

Any number between 8 - 12 (inclusive) gives a Abort trap 6, whereas numbers that are >= 13 are fine.

So two questions arise:

  1. Why is char s[12] = "hello, " not okay while 7 is? It seems like an array of size 13is needed for the trailing '\0', but why was 7 okay then? Shouldn't it be 8?
  2. Why is 7 okay in the first place? Sizes 8-12 contain "hello, " just like a size 7 char array, and are written beyond their original array size, and yet 7 gets away with it while others don't.

Upvotes: 0

Views: 151

Answers (2)

Zan Lynx
Zan Lynx

Reputation: 54325

You'd have to read the machine code to figure this out. As Jonathan Leffler said, this is undefined behavior.

It probably depends on the compiler and how it lays things out in memory. There's no requirement that an array of size 7 gets an actual 7 bytes. It might decide to pad it out to 16 for a better stack layout. Or it might place it in a different position so there's a zero after it and some extra room while the larger arrays get different placements.

Or if you compile with optimizations on, the compiler might be unrolling a loop of size 7 into "correct" code which reduces to a simple puts("hello, world"); but is unable to inline a larger loop.

I did a little experiment out of curiosity and with GCC on Linux the answer is that in 64-bit mode it always works because there is enough room in the 8 byte char *t pointer to store "world".

In 32 bit mode it fails as you describe because it overwrites the return stack. But 7 works sort of, with garbage data, because it doesn't find a zero until it is past the return value, then it "appends" into open stack space. The printed result looks like hello, ��#m�?��world

Upvotes: 1

Hariom Singh
Hariom Singh

Reputation: 3632

I don't Know which compiler you are using but xcode complains about it

Initializer error Initializer -string for char array is too long

Upvotes: 0

Related Questions