calloc上的分段错误,分配大小

时间:2017-06-18 20:05:37

标签: c

我已编写代码来模拟选举,这可以按预期工作,但是当我将BALLOT_SIZE修改为7并更改New_Random_Ballot()中int v[BALLOT_SIZE] = {0,1,2,3,4,5,6}的定义时,语句struct Ballot * New_Ballot = calloc(1, sizeof(struct Ballot *));给我一个分段错误。应该注意的是,将BALLOT_SIZE设置为6并修改int v[BALLOT_SIZE] = {0,1,2,3,4,5}的定义以及这些变量的所有较小设置(例如长度4,3或2)都可以正确执行。为清楚起见,我已删除了对阵列进行洗牌的代码。

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#define BALLOT_SIZE 5
#define NUM_VOTERS 50

struct Ballot {
    int votes[BALLOT_SIZE];
};

struct Ballot * New_Random_Ballot() {

    int v[BALLOT_SIZE] = {0,1,2,3,4}; 
    struct Ballot * New_Ballot = calloc(1, sizeof(struct Ballot *));

    for (int j = 0; j < BALLOT_SIZE; j++) {
        New_Ballot->votes[j] = v[j];
    }
    return New_Ballot;
}

void Hold_Election(struct Ballot * Election[NUM_VOTERS]) {
    for (int i=0; i < NUM_VOTERS; i++) {
        Election[i] = New_Random_Ballot();
    }   
}

int main() {
    struct Ballot * Election[NUM_VOTERS];
    Hold_Election(Election);

    //free memory
    for (int i=0; i < NUM_VOTERS; i++) {
        free(Election[i]);
    }
    return 0;
}

我已经尝试捕获calloc调用的返回值并将其检查为NULL,但在能够检查返回值之前,它出错(在此示例中,BALLOT_SIZE为7):

struct Ballot * New_Random_Ballot() {

    int v[BALLOT_SIZE] = {0,1,2,3,4,5,6}; 
    struct Ballot * New_Ballot = calloc(1, sizeof(struct Ballot *));

    if (New_Ballot == NULL) {
        perror("could not allocate ballot\n");
    }

    for (int j = 0; j < BALLOT_SIZE; j++) {
        New_Ballot->votes[j] = v[j];
    }
    return New_Ballot;
}

1 个答案:

答案 0 :(得分:2)

问题在于:

calloc(1, sizeof(struct Ballot *));  // Ballot* is a pointer of size 4 or 8

替换为:

calloc(1, sizeof(struct Ballot));  // struct Ballot is a structure of some size

正如下面@Olaf正确指出的那样,指针大小可能取决于CPU。上面的原始答案需要一点澄清。

对于任何数据类型,结构或联合AnyType:

,ISO标准保证了这种相等性
sizeof(AnyType*) == sizeof(void*)

void *的大小由CPU架构定义。在32位平台上,指针长度为4个字节,在64位平台上,长度为8个字节。

在16位平台上,例如i386,指针通常为16位长,但也有远指针,sizeof(void far*) 通常 32位(16位用于段,16位用于地址)。

在8位平台上,例如i8051,逻辑会指示指针为8位宽,但这不是很有用,因此指针在8位CPU上通常为16位宽。 8bit cpus上通常没有与指针相关的段,程序员负责管理远存储器。即通过设置适当的控制寄存器来改变可见的扩展存储器页面。