1

当我运行以下代码时,出现运行时检查失败 #2 - 变量“obj”周围的堆栈已损坏错误。我知道这是因为覆盖'obj'的边界导致堆栈损坏而失败。那么这里如何防止缓冲区溢出。

typedef struct _INFO {
    int Count;
} Info, *InfoPtr;

#define MAX_COUNT               10

//void fn(Info(*obj)[MAX_COUNT])
void fn(Info (*obj)[MAX_COUNT])
{
    for (int i = 0; i < 2; i++) 
    {
        obj[i]->Count = i;
    }
}

int main()
{
    Info    obj[MAX_COUNT];
    fn(&obj);
    return 1;
}
4

1 回答 1

5

Info (*obj)[MAX_COUNT]您说的是指向类型对象obj数组的指针。MAX_COUNTInfo

但是随后您将其obj[i]->Count = i用作对象指针数组obj。即。不是一回事。这会导致未定义的行为InfoInfo *obj][]

解决方案非常简单,不要将指向数组的指针作为参数传递,将其视为对象数组而不是指向对象的指针。

IE

typedef struct Info {
    int Count;
} Info;

#define MAX_COUNT               10

void fn(Info *obj, const size_t elems)
{
    for (size_t i = 0; i < elems; i++) 
    {
        obj[i].Count = i;
    }
}

int main()
{
    Info    obj[MAX_COUNT];
    fn(obj, MAX_COUNT);
}

最显着的变化是fn函数声明,它接受一个指向. Info这是因为数组自然会衰减为指向其第一个元素的指针。我还添加了一个参数来保存数组中元素的数量,所以函数知道它。这使函数更通用,您可以将不同大小的不同数组传递给它。

我也改变了main功能,根本不返回任何东西。由于 C99 标准,main没有显式的函数将由编译器return隐式获取 a 。从函数return 0返回通常被视为“好的”或“没有失败”。返回非零值被视为失败或错误。0main

我还更改了您的结构的名称。具有前导下划线后跟大写字母的名称(C 或预处理器)由编译器和标准 C 库在所有范围内保留。此外,结构标记名称存在于单独的命名空间中,因此您可以将结构名称与类型名称(类型别名,由 定义typedef)具有相同的名称。我还删除了InfoPtr类型名称,使用诸如类型名称之类的指针混淆了代码,使其可读性和可维护性降低。

于 2017-06-08T10:39:42.303 回答