为什么在C中这个段错误?

时间:2015-03-31 20:22:22

标签: c

我无法弄清楚为什么这个微小的C程序会出现段错误:

#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;
}

编译:

  

$ gcc -O0 test.c -o run

输出:

  

$ ./run 1000

     

$输入1000

     

$ Sanity check ...

     

$ [1] 17529分段错误(核心转储)./ run 1000

现在,如果我将其中一个for循环向下移动:

#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;
}

一切正常..相同的编译步骤,这是输出:

  

$ ./run 1000

     

$输入1000

     

$ Sanity check ...

     

$没有段错误。耶!

我做一个大型20MB malloc的原因是尝试从我正在分析的代码中删除缓存效果。感觉两个实现都应该工作,但第一个是在对20MB阵列进行malloc时的段错误。我错过了一些明显的东西吗?

感谢。

3 个答案:

答案 0 :(得分:18)

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

您正在分配in个字节,而不是in个整数。尝试:

malloc(sizeof(int) * in);

您的第二次分配有效,因为sizeof(char)1

答案 1 :(得分:5)

本声明

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

错了。

我认为你的意思是

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

答案 2 :(得分:1)

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