【问题标题】:C program crashes when trying to refer to struct array尝试引用结构数组时 C 程序崩溃
【发布时间】:2014-07-07 23:55:19
【问题描述】:

我正在尝试制作一个简单的数据库程序,但是当我到达这一行时

int idSearch(product* itens, int id) {
    int i = 0;
    for(i; i < size; i++) {
        if(itens[i].id == id) //<=== This line
            return i;
    }
    return ITEM_NOT_FOUND;
}

程序停止响应。 size 在程序开始时设置为全局变量

FILE* flog;
FILE* db;
FILE* sizef;
int size = 100;

这个函数被调用

void newProduct(product* itens, char name[64], int id, float price) {
    int pos = idSearch(itens, 0);

    if(idSearch(itens, id) != ITEM_NOT_FOUND) {
        printf("Erro, o produto ja existe");
        return;
    }...

items 定义为

itens = (product*) calloc(sizeof(product), size); 

并且产品是这样定义的struct

typedef struct{
    char    name[64];
    int     id;
    float   price;
    int     amount;
} product;

首先我认为问题在于我没有使用-&gt; 运算符,但是当我尝试编译器时说它不对。

我在 Windows 7 x64 上使用 Code::Blocks 和 GCC 编译器

**编辑:整个代码可以在这里找到:http://hastebin.com/atulajubar.tex

希望尽快得到答复,在此先感谢

【问题讨论】:

  • 第一个代码块中的size 定义在哪里?它的定义是什么?
  • size 被定义为在主函数中设置为 100 的全局变量。虽然它被初始化为 0
  • 显示itens的定义?也就是说,从你传递给newProduct的地方?
  • 很难从您的代码示例中看出这个函数的值是什么。另外,itens 是如何分配的?什么尺寸?
  • 习惯上将数组的大小传递给任何需要它的函数。不要依赖全局。 newProductidSearch 都应该将适当的大小作为附加参数传递。正如所写的那样,根本不可能回答你的问题,因为你没有给出可重复的步骤,所以猜测和推测是你所能期望的最好的(顺便说一句,这不是一个好问题)。我的建议。丢失全局 size 使其成为数组创建者的本地变量,并在需要时将其与数组基地址一起作为参数传递。 (如果使用得当,calloc 也可以)。

标签: c arrays windows struct crash


【解决方案1】:

**编辑:你打错了calloc()。签名为:void *calloc(size_t nelem, size_t elsize); 您首先给它大小,然后是 元素的数量。换个角度看看你的问题是否解决了。

另外,当调用(修复后:)itens = (product*) calloc( size, sizeof(product) ); 时, 执行此操作后检查 itens 是否为 NULL 很重要。如果 calloc 不能给你正确的内存量,我相信它会返回一个 NULL 指针。检查这个,因为如果你得到 NULL 回来,那是你的问题。

一种好的、简单、便携的检查方法是:

if(!itens){
   fprintf(stderr, "Error! Could not allocate memory!\n");
   exit(1);
}

另外,正如 WhozCraig 建议的那样,请确保您的代码包含 #include &lt;stdlib.h&gt;,这是 calloc() 手册页中的要求。

【讨论】:

  • 我真的怀疑 gcc 编译的程序如果缓冲区溢出会崩溃。
  • @Kasama 这很可能意味着您已经释放了内存和/或正在使用不确定的指针。 printf("itens=%p\n", itens); 紧跟在calloc() 之后,同样在您的其他函数内部可能 公开一个垃圾指针,但不会 公开一个错误释放的指针。这个应用程序听起来不大。你有没有机会简单地发布所有源来一劳永逸地解决这个问题?
  • @Kasama 再次查看我的编辑。您曾经/正在使用错误的参数调用 calloc() - 这很可能至少是您的问题之一。
  • @Ricky Mutschlechner 是的。这就是我建议malloc的原因。但似乎没有人注意到那个 calloc 有什么问题:D
【解决方案2】:

这是错误的:

if((db = fopen(DB_PATH, RB))==NULL)
{
    if((db = fopen(DB_PATH, RWB))==NULL)
    {
        exit(1);
    }
    else
    {
        itens = (product*) calloc(sizeof(product), size);
        fwrite(itens, sizeof(product), size, db);
        rewind(db);
    }
}
fread(itens, sizeof(product), size, db);

如果您在当前工作目录中有 DB_PATH 文件,则第一个 fopen() 将成功,items 分配将永远不会发生。仅当文件找到,但随后成功创建,items 才会包含有效分配,假设calloc 工作。

应该删除else 条件:

// note calloc parameter order addressed.
itens = calloc(size, sizeof(product));
if (itens == NULL)
{
    perror("Failed to allocate items.");
    exit(EXIT_FAILURE);
}

if((db = fopen(DB_PATH, RB))==NULL)
{
    if((db = fopen(DB_PATH, RWB))==NULL)
        exit(EXIT_FAILURE);

    fwrite(itens, sizeof(product), size, db);
    rewind(db);
}

fread(itens, sizeof(product), size, db);

还有大量错误检查需要处理,但无论如何都需要解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-29
    • 2022-01-09
    • 2015-08-22
    • 2014-06-12
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多