我的目标是优化内存使用...在任何教程中我从未见过,这使我认为这不是正确的方法
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Player {
char* username;
int hp;
int mp;
};
int main(void) {
struct Player test, *p = &test;
p->username = (char*)malloc(50 * sizeof(char));
scanf("%s", p->username);
p->username = realloc(p->username, (strlen(p->username) + 1) * sizeof(char));
printf("%s", p->username);
return 0;
}
答案 0 :(得分:0)
优化内存使用率的正确方法?
临时重复使用的缓冲区通常很宽大且大小固定。
为成员.username
分配适当大小的内存是有意义的,因为代码可能需要数百万个struct Player
。
IOW,将分配用于代码的可变大小方面。如果struct Player
用于2人棋牌游戏,那么char username[50]
的大小是合理的。对于多玩家宇宙,char *
很有道理。
考虑一次单个大小合适的通话,而不是两次呼叫*alloc()
。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// Reasonable upper bound
#define USERNAME_SIZEMAX 50
struct Player {
char* username;
int hp;
int mp;
};
int main(void) {
puts("Enter user name");
// Recommend 2x - useful for leading/trailing spaces & detecting excessive long inputs.
char buf[USERNAME_SIZEMAX * 50];
if (fgets(buf, sizeof buf, stdin) == NULL) {
puts("No input");
} else {
trim(buf); // TBD code to lop off leading/trailing spaces
if (!valid_name(buf)) { // TBD code to validate the `name`
printf("Bad input \"%s\"\n", buf);
} else {
struct Player test = { 0 }; // fully populate
test.username = malloc(strlen(buf) + 1);
// Maybe add NULL check here
strcpy(test.username, buf);
// Oh happy day!
printf("%s", p->username);
return EXIT_SUCCESS;
}
}
return EXIT_FAILURE;
}
答案 1 :(得分:-1)
一些提示:
a)示例代码太小了
b)切勿将malloc()
用于您永远想要的一种。相反,请预先分配(例如,作为全局变量)或(如果足够小)使用局部变量,以避免malloc()
的开销。例如:
int main(void) {
struct Player test, *p = &test;
char userName[50];
p->username = userName;
c)不要将数据散布到整个地方。您希望所有数据都在同一位置(在最少的缓存行中,并且同时使用的数据段尽可能地彼此靠近)。一种方法是组合多个项目。例如:
struct Player {
char username[50];
int hp;
int mp;
};
int main(void) {
struct Player test, *p = &test;
d)如果某事物最多占用50个字符;不要费心使用realloc()
来浪费CPU时间并可能浪费更多的内存。不要忘记malloc()
和realloc()
的内部代码会将元数据添加到每个分配的内存中,这可能会花费额外的16个字节或更多。
一般而言;为了提高性能,应完全避免使用malloc()
和realloc()
(以及new()
和...)(尤其是对于较大的程序)。他们“随机”地将数据散布到各处,并破坏了获得良好位置的希望(这对于最大程度地减少多个非常昂贵的事情非常重要-缓存未命中,TLB未命中,页面错误,交换空间使用等)。
注意:scanf()
和gets()
也应被禁止。它们无法防止缓冲区溢出(例如,当只有50个字符分配足够的内存时,用户故意提供50个字符以上的内存,目的是故意破坏/破坏其他数据),这将导致巨大的安全漏洞。