2015-03-31 83 views
4

我想不通,为什么这个小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 1000

$输入1000

$完整性检查...

$ [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

$完整性检查...

$无段错误。好极了!

为什么我在做一个大的20MB malloc的原因是尝试从我正在分析的代码中删除缓存效果。感觉这两个实现都应该可以工作,但是当malloc-20MB数组时,第一个实现会发生段错误。我在这里错过了很明显的东西吗

谢谢。

回答

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

你分配in字节,而不是in整数。尝试:

malloc(sizeof(int) * in); 

你的第二个分配工作,因为sizeof(char)1

+2

此外,malloc'的'铸造相当灰心。 – 2015-03-31 20:25:53

+0

谢谢!所以我做了一些愚蠢的事情。啊。 – sidmontu 2015-03-31 20:31:07

+0

@MichałSzydłowski为什么malloc的投射不受欢迎?没有一个有效的解释,你不能轻视有效的答案 – bizzehdee 2015-03-31 23:09:13

5

本声明

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

是错误的。

我想你的意思

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

是的,谢谢你,我已经做出了改变,它按预期工作。 – sidmontu 2015-03-31 20:31:42

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 
+0

谢谢!我只是为了测试而写了这个小程序。它代表了我实际编写的流程,以便找出段错误发生的位置和原因,而不必处理“生产”代码周围的所有其他复杂性。你提到的格式化的东西(例如检查argc值和处理错误)是在我正在编写的实际应用程序中处理的 - 我愚蠢地忽略了int数组的malloc,并且了解了不从这个类型中强制mallocs。所以,感谢您的投入! – sidmontu 2015-04-01 08:52:06