我无法弄清楚为什么这个微小的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时的段错误。我错过了一些明显的东西吗?
感谢。
答案 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