Q: Why does this segfault in C? I can't figure out why this tiny C program segfaults:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){

    int in = atoi(argv[1]);
    printf("Input %d\n",in);

    int *n = (int *)malloc(in);
    int j;

    for (j=0;j<in;j++)
        n[j] = j;

    printf("Sanity check...\n");

    char *c = (char *)malloc(1024*1024*20);
    int i;
    for (i=0; i<20*1024*1024;i++)
        c[i] = i;

    printf("No segfault. Yay!\n");

    return 0;
}

Compiled with:

$ gcc -O0 test.c -o run

Output:

$ ./run 1000
$ Input 1000
$ Sanity check...
$ [1]     17529 Segmentation fault (core dumped)  ./run 1000

Now if I move one of the for-loops down like this:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]){

    int in = atoi(argv[1]);
    printf("Input %d\n",in);

    int *n = (int *)malloc(in);
    int j;

    printf("Sanity check...\n");

    char *c = (char *)malloc(1024*1024*20);
    int i;
    for (i=0; i<20*1024*1024;i++)
        c[i] = i;

    printf("No segfault. Yay!\n");

    for (j=0;j<in;j++)
        n[j] = j;
    
    return 0;
}

everything works.. same compilation step, this is the output:

$ ./run 1000
$ Input 1000
$ Sanity check...
$ No segfault. Yay!

Reason why I'm doing a large 20MB malloc is to try and remove cache effects from the code I am profiling. It feels like both implementations should work, but the first one segfaults when malloc-ing the 20MB array. Am I missing something obvious here?
Thanks.

A: This statement
int *n = (int *)malloc(in);

is wrong.
I think you mean
int *n = (int *)malloc(in * sizeof( int ) );


A: int in = atoi(argv[1]);
int *n = (int *)malloc(in);

You're allocating in bytes, not in integers.  Try:
malloc(sizeof(int) * in);

Your second allocation works because sizeof(char) is 1.

A: given the posted code,
lets just run down the reasons it seg faults.

my comments are interspersed with the code

#include <stdio.h>
#include <stdlib.h>

// argc is not used, so the compiler will raise a warning
int main(int argc, char *argv[])
{

    // the value of argc was not checked to assure a parameter is present
    // so a 'usage' message was not output when no parameter is present
    // or too many parameters are present
    // note: 'in' is (IMO) a poor name for a local variable
    int in = atoi(argv[1]);
    // missing check to assure the value if 'in' is greater than 0
    // and handling the error when the value is <= 0

    printf("Input %d\n",in);

    // in C, the returned value from calls to malloc(), and family,
    //       should not be cast
    // the returned value is (per the definition of 'n')
    // to be a pointer to an array of int's
    // which should be written as:
    // int *n = malloc( in * sizeof int );
    // the returned value from malloc(), and family of functions,
    //     needs to always be checked (!= NULL)
    //     to assure the operation was successful
    int *n = (int *)malloc(in);
    int j;

    // because the malloc call did not ask for a memory allocation
    // of 'in' int's, so this code block corrupts the heap
    // by writing past the end of the allocated memory
    for (j=0;j<in;j++)
        n[j] = j;

    printf("Sanity check...\n");

    // in C, the returned value from calls to malloc(), and family of functions,
    //       should not be cast
    // the returned value needs to be checked (!= NULL) to assure the operation
    //       was successful
    // the calculated value: 1024*1024*20 should be calculated by the
    //       compiler, not repeatedly at run time.
    //       so insert 'const int twentyMillion = 1024*1024*20;'
    //       at beginning of program
    char *c = (char *)malloc(1024*1024*20);
    int i;

    // to avoid repeatedly calculating the 20million value, use a const (as above)
    // so this line would be: for ( i=0; i<twentyMillion; i++ )
    for (i=0; i<20*1024*1024;i++)
        // the value of 'i' will massively exceed the value that can be kept in a char
        //  I.E. 255 so this loses data
        //  suggest replacing following line with: j = i%256;  c[i] = j;
        // to make it obvious what is going on
        c[i] = i;

    printf("No segfault. Yay!\n");

    return 0;
} // end function: main

