Как назначить временное значение для 2d массива - PullRequest
0 голосов
/ 13 марта 2019

Итак, у меня есть двумерный массив структур, в которых я храню данные из файла CSV.Я читаю в строках из файла, а затем хочу назначить их значение в массиве 2d в качестве этой строки.Так, например, position [0] [0] будет «красным», а position [1] [1] будет «синим» или что-то в этом роде.Проблема в том, что я читаю символы из файла и сохраняю их во временной строке, а затем хочу присвоить это значение временной строки текущей позиции, в которой я нахожусь.Итак, у меня есть значение temp как «red», и я хочу, чтобы [0] [0] было «красным», тогда оно считывает больше из файла, а temp теперь «blue», и я хочу, чтобы [0] [1] было «blue»».Когда я назначаю [0] [0] = temp, тогда [0] [1] = temp они пишут друг над другом (так как это указатель).Я пробовал strdup (temp), но это, похоже, не решает проблему, либо они все равно иногда перезаписывают друг друга.Я знаю, что могу использовать strcpy, но для strcpy мне нужно иметь другую строку, чтобы скопировать ее, поэтому я попытался сделать это, просто создав новый массив символов каждый раз, но это тоже не работает.Это все еще переписывается.Я знаю, что мог бы решить эту проблему, если бы каждый раз, когда я присваивал значение, я создавал новый массив char с новым именем и указывал на этот массив char, но это для очень большого CSV-файла, поэтому мне пришлось бы создать около 10 миллионови я не знаю, как это сделать, и кажется, что должен быть более простой способ.

Любая помощь очень ценится, спасибо!

struct node {
    char* value;
};

char temp[500];
struct node ** arrayofnodes[35];
for(int i=0; i<35; i++) {
    arrayofnodes[i] = malloc(test * sizeof (struct node));
    for(int j=0; j<test; j++) arrayofnodes[i][j] = malloc(sizeof (struct node));
}


//(all of this below happens inside a function because it is going to be called like 10 million times)
    arrayofnodes[row][count]->value=temp; //way 1
    arrayofnodes[row][count]->value=strdup(temp); //way 2
    char fun[500];
    strcpy(fun,temp);
    arrayofnodes[row][count]->value=fun;//way 3

Ответы [ 2 ]

1 голос
/ 14 марта 2019

arrayofnodes[i] = malloc(N * sizeof (struct node)); оставляет достаточно места для N структур.То, что вы хотите, это пространство для N указателей структуры.

Однако я не думаю, что это ваша главная проблема.Допустим только «путь 2» - вам нужно создать хранилище для каждой новой строки, которую вы прочитали.«way 1» повторно использует хранилище «temp», а «way 3» повторно использует хранилище «fun», которое станет недействительным, как только вы выйдете из функции.

If «way»2 "не работает для вас, я бы посмотрел на код, генерирующий row и count.Эти индексы всегда меньше 35 и test соответственно?

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

При использовании malloc или strdup вам необходимо дополнительно 16 байтов для управления.
Когда вы выделяете много малой памяти, это дополнительное пространство также занимает много памяти.
Итак, рассмотрим собственную управляющую память или tcmalloc, jemalloc

Ниже приведены данные теста:

gcc -otest test.c -Wall -O3 -g

[test_strdup] cost time: 1085247 us, use memory: 839.81 MB
[test_optimized] cost time: 394635 us, use memory: 411.71 MB

gcc -otest test.c -Wall -O3 -g -ltcmalloc

[test_strdup] cost time: 627160 us, use memory: 461.07 MB
[test_optimized] cost time: 397938 us, use memory: 422.85 MB

gcc -otest test.c -Wall -O3 -g -ljemalloc

[test_strdup] cost time: 749875 us, use memory: 481.77 MB
[test_optimized] cost time: 330825 us, use memory: 451.96 MB

Ниже приведен тестовый код

Просто для сравнения распределения памяти в тестовом коде есть утечка памяти.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/sysinfo.h>

#define ROWS 35
#define COLS (1000*10000/ROWS)
#define MB   (1024*1024)
#define TEST_STR "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

struct node {
    char *value;
};

long current_time()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000L + tv.tv_usec;
}

long current_usemem()
{
    FILE *fp;
    long resident = 0;

    fp = fopen("/proc/self/statm", "r");
    if (fp) {
        if (fscanf(fp, "%*s %ld ", &resident) != 1)
            resident = 0;
        fclose(fp);
    }
    resident *= 4096;

    return resident;
}

void test_strdup()
{
    char temp[500];
    struct node **arrayofnodes[ROWS];
    int i, j;
    long start_time, end_time;
    long start_usemem, end_usemem;

    strcpy(temp, TEST_STR);
    start_usemem = current_usemem();
    start_time = current_time();

    for(i = 0; i < ROWS; i++) {
        arrayofnodes[i] = (struct node **)malloc(COLS * sizeof(struct node *));
        for(j = 0; j < COLS; j++) {
            arrayofnodes[i][j] = (struct node *)malloc(sizeof (struct node));
        }
    }

    for(i = 0; i < ROWS; i++) {
        for(j = 0; j < COLS; j++) {
            arrayofnodes[i][j]->value = strdup(temp);
        }
    }

    end_time = current_time();
    end_usemem = current_usemem();
    printf("[%s] cost time: %ld us, use memory: %.2f MB\n",
           __FUNCTION__, end_time - start_time,
           (end_usemem - start_usemem) / 1024.0 / 1024);
}

struct memory_chunk {
    struct memory_chunk *next;
    char *cur;
    char *end;
    char buf[0];
};

struct memory_pool {
    struct memory_chunk *head;
};

void *pool_alloc(struct memory_pool *pool, size_t size)
{
    void *ret;
    struct memory_chunk *chunk;

    chunk = pool->head;
    if (chunk == NULL || chunk->cur + size >= chunk->end) {
        size_t len = (size < MB ? MB : size + sizeof(*chunk));
        chunk = (struct memory_chunk *)malloc(len);
        chunk->next = pool->head;
        chunk->end = (char *)chunk + len;
        chunk->cur = chunk->buf;
        pool->head = chunk;
    }

    ret = chunk->cur;
    chunk->cur += size;
    return ret;
}

char *pool_strdup(struct memory_pool *pool, const char *s)
{
    size_t size = strlen(s) + 1;
    void *ret = pool_alloc(pool, size);
    memcpy(ret, s, size);
    return ret;
}

void test_optimized()
{
    char temp[500];
    struct node ***arrayofnodes;
    int i, j;
    long start_time, end_time;
    long start_usemem, end_usemem;
    struct memory_pool pool = {NULL};

    strcpy(temp, TEST_STR);
    start_usemem = current_usemem();
    start_time = current_time();

    arrayofnodes = (struct node ** *)pool_alloc(&pool, ROWS * sizeof(struct node **));
    for(i = 0; i < ROWS; i++) {
        arrayofnodes[i] = (struct node **)pool_alloc(&pool, COLS * sizeof(struct node *));
        for(j = 0; j < COLS; j++) {
            arrayofnodes[i][j] = (struct node *)pool_alloc(&pool, sizeof(struct node));
        }
    }

    for(i = 0; i < ROWS; i++) {
        for(j = 0; j < COLS; j++) {
            arrayofnodes[i][j]->value = pool_strdup(&pool, temp);
        }
    }

    end_time = current_time();
    end_usemem = current_usemem();
    printf("[%s] cost time: %ld us, use memory: %.2f MB\n",
           __FUNCTION__, end_time - start_time,
           (end_usemem - start_usemem) / 1024.0 / 1024);

}

int main()
{
    test_strdup();
    test_optimized();

    return 0;
}
...