Это правильный способ оптимизировать использование памяти? - PullRequest
1 голос
/ 23 марта 2019

Моя цель - оптимизировать использование памяти ... Я никогда не видел этого ни в одном учебном пособии, которое заставляет меня думать, что это неправильный способ сделать это

#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;
}

Ответы [ 2 ]

0 голосов
/ 23 марта 2019

правильный способ оптимизировать использование памяти?

Временные повторно используемые буферы часто могут быть щедрыми и иметь фиксированный размер.

Выделение нужного объема памятиимеет смысл для члена .username, поскольку код может быть для миллионов struct Player.

IOW, используйте распределение для аспектов кода с переменным размером.Если struct Player было для шахмат с двумя игроками, размер 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;
}
0 голосов
/ 23 марта 2019

Несколько советов:

а) пример кода слишком мал, чтобы иметь значение

b) никогда не используйте malloc() для чего-то, что вы всегда захотите. Вместо этого предварительно выделите (например, как глобальную переменную) или (если она достаточно мала) используйте локальную переменную, чтобы избежать издержек malloc(). E.g.:

int main(void) {
    struct Player test, *p = &test;
    char userName[50];
    p->username = userName;

в) Не распространяйте данные повсюду. Вы хотите, чтобы все данные находились в одном и том же месте (в наименьшем количестве строк кэша, с частями данных, которые используются в одно и то же время как можно ближе друг к другу). Один из способов сделать это - объединить несколько предметов. E.g.:

struct Player {
    char username[50];
    int hp;
    int mp;
};

int main(void) {
    struct Player test, *p = &test;

d) Если что-то занимает (максимум) 50 символов памяти; не тратьте время на использование realloc(), чтобы тратить впустую процессорное время и потенциально тратить больше памяти. Не забывайте, что внутренний код для malloc() и realloc() добавит метаданные к каждому выделенному фрагменту памяти, который, вероятно, будет стоить дополнительно 16 байтов или более.

В общем; для производительности следует полностью избегать malloc() и realloc()new() и ...) (особенно для более крупных программ). Они распространяют данные «случайным образом» повсюду и разрушают любую надежду на получение хорошей локализации (что важно для минимизации множества очень дорогих вещей - кеш-пропусков, пропусков TLB, сбоев страниц, использования пространства подкачки, ...).

Примечание: scanf() и gets() также должны быть запрещены. Они не позволяют предотвратить переполнение буфера (например, пользователь предоставляет более 50 символов, когда для 50 символов выделено только достаточно памяти для преднамеренной очистки / повреждения других данных), что приводит к огромным дырам в безопасности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...