在我正在编写的程序中,我有一系列帐户(帐户是我制作的结构)。我需要对程序中的所有函数和线程都可见。但是,在主要功能出来之前,我不知道它的大小。所以我创建它: 帐户*帐户;
并尝试使用以下方法为其分配空间:
number of accounts = 100 //for example
accounts = (account*)malloc(numberOfAccounts * sizeof (account));
然而,它似乎是将数组的大小调整为大于它需要的大小。例如,accounts[150]
存在,依此类推。
我做错了什么吗?如何才能使帐户的大小正好100
?
感谢
答案 0 :(得分:5)
你不能这样做 - malloc()
没有提供关于它实际分配多少内存的任何保证(除非它成功,它将返回一个指向的指针至少同样按照你的要求)。如果访问所要求范围之外的任何内容,则会导致未定义的行为。这意味着它似乎可行,但你无能为力。
BTW,在C中,您不需要对malloc()
的返回值进行类型转换。
答案 1 :(得分:4)
即使看起来像它,accounts[150]
也不存在。
那为什么你的程序继续运行?好吧,那是因为即使accounts[150]
不是真正的元素,它也位于允许程序访问的内存空间内。
C不包含索引的运行时检查 - 它只是计算适当的地址并访问它。如果您的程序无法访问该内存地址,则会因分段错误(或者在Windows术语中出现访问冲突)而崩溃。另一方面,如果允许程序 访问该内存地址,那么它只会将该地址处的任何内容视为account
。
如果你试图修改它,几乎任何事情都可能发生 - 取决于各种各样的因素,它可以修改程序中的一些其他变量,或者给出一些非常不幸的情况,它甚至可以修改程序代码本身,可能导致各种时髦的行为(包括崩溃)。如果malloc(无论出于何种原因)分配的内存多于您明确请求的内存(这是可能的话),甚至可能无法观察到任何副作用。
如果要确保在运行时捕获此类错误,则必须实现自己的检查和错误处理。
答案 2 :(得分:1)
我似乎无法发现您提供的内容有任何问题。如果你有一个结构,例如:
struct account{
int a,b,c,d;
float e,f,g,h;
}
然后你可以使用以下方法创建一个帐户数组:
struct account *accounts = (struct account *) malloc(numAccounts * sizeof(account));
请注意,对于C,void*
(retun类型的malloc)的强制转换是不必需。它会自动升级。
[编辑]
唉唉!我现在看到你的问题!对。是的,您仍然可以访问帐户[150],但基本上会发生的事情是accounts
将指向某个内存位置。 accounts[150]
只是进一步指向结构大小的150倍。这样做可以得到相同的结果:
*(accounts + 150)
,基本上说:给我位置帐户的价值+ 150。
此内存根本不保留,因此会导致未定义的行为。它基本上归结为:不要这样做!
答案 3 :(得分:0)
你的代码很好。当你说帐户[150]退出时,你的意思是退出还是存在?
如果您的代码在访问帐户时崩溃[150](假设numberOfAccounts = 100),那么可以预期您正在访问您分配的内存之外的内存。
如果你的意思是存在它并不是真的,你只是走出数组的末尾,你得到的指针是与你分配的不同的内存区域。
答案 4 :(得分:0)
如果此地址非零,则来自malloc结果指针的100
结构的帐户大小非常明显。
答案 5 :(得分:0)
仅仅因为它有效并不意味着它作为你分配的内存的一部分存在,很可能它属于其他人。
C并不关心或知道您的帐户*来自malloc,它只知道这是一个指向sizeof(account)的内存指针。
accounts [150]从指针中的值访问第150个帐户大小的对象,可能是随机数据,也可能是其他内容,具体取决于您的系统,甚至可能是您的程序。
事情似乎“奏效”的原因是,无论发生什么事情都不重要,但情况可能并非总是如此。