C структура неизвестного размера - PullRequest
1 голос
/ 30 июля 2011

Я пишу приложение со следующей динамической структурой конфигурации:

typedef struct {
    char apphash[41];
    char filenames_count;
    char * filename[64];
} config;

Но этот код неправильный, я не могу понять, как правильно копировать данные из c-> filename [0] и в него; c - указатель на конфигурационную структуру, динамически размещаемую как

config * c = (config *) malloc( 42 + 64 * 2 ) // alloc for 2 filenames. can realloc() later.

Сегфо, если я использую что-то вроде strcpy(c->filename[0],"file1.txt").

Может кто-нибудь помочь мне с этим?

В настоящее время я использую прямое вычисление адреса, как

strcpy(
    (char*) 
    ((unsigned long) c + 42 /* apphash + filenames_count */ + 
    64 * 0 /* first item */ ),
    "file1.txt"
);

и это работает, конечно.

Видите ли, я больше программист на ассемблере, чем на C, но я бы хотел, чтобы этот код был более понятным для человека. Этот код выглядит так плохо, потому что я новичок в C.


О, я дал плохое описание ситуации. Извините за это: (
Реальный код выглядит так:

config * c = (config*) malloc( 42 + 64 * 2 );
// we may realloc() it later if we are going to add more filenames.

// failing example how I do copy one default filename
strcpy(c->filename[0],"file1.txt");

// working example (i386)
strcpy((char*)((unsigned long) c + 42 + 64 * 0),"file1.txt");

Я использую полностью статический тип структуры, потому что в следующий раз он будет загружен непосредственно из файла. Вот почему я не могу использовать указатели внутри структуры, мне нужны реальные данные для размещения там.
Я проверяю все длины, никаких BOF в реальном коде, я просто опустил все это здесь.

Я все еще не нашел хорошего решения для этого.

Еще раз спасибо и извините за неверную информацию о вопросе.

Ответы [ 4 ]

4 голосов
/ 30 июля 2011

Я предполагаю, что у вас много имен файлов, так как у вас есть filenames_count. Попробуйте

config_obj.filename[0] = strdup("file1.txt")
3 голосов
/ 30 июля 2011

В вашей структуре вы выделяете массив указателей на символы, а не массив символов.Вы также должны явно указывать цели указателей или, по крайней мере, сделать так, чтобы структура содержала также массивы самих символов:

char filename[64][MAX_PATH+1];

Замените MAX_PATH максимальной длиной любого имени файла.Имейте в виду, что это не очень элегантное решение, хотя и очень простое, потому что вы тратите много места.

Ваш прямой адрес вычисляет что-то другое: он помещает строку непосредственно в пространство, выделенное дляуказатели (а это ужасно неправильная вещь ™)

2 голосов
/ 30 июля 2011

Прямо сейчас config - это тип , что означает структуру, которую вы определили. Вы не показываете нам идентификатор, относящийся к фактической переменной типа config.

Итак, во-первых, нам нужен экземпляр типа config. Вы либо сделаете

config c;
... c.filename ...

обратите внимание, что оператор доступа к структуре - ., или вы сделаете что-то вроде

config *p = malloc(config)
/* error checking */
...c->filename ...

где -> - оператор разыменования и доступа к указателю. Первая форма предпочтительна, если только у вас нет причины хотеть динамического размещения (что, увы, часто случается в c).

Тогда вы должны выяснить, кем именно вы хотите filename. Так как вы выделили пространство для 64-символьных указателей, которые не указывают на выделенную память (кроме как по чистой случайности, а не по памяти, которую вы имеете в виду). Вы, вероятно, хотели {*} char filename[64] (одно имя файла может иметь длину до 63 символов (чтобы оставить место для нулевого завершения)), в этом случае вы должны использовать

strcpy(c.filename,"file1.txt");
/* or */
strcpy(p->filename,"file1.txt");

в зависимости от того, как вы распределили структуру в первую очередь.

Если вы действительно хотите список имен файлов, тогда вы можете захотеть char *filenames[64], но вам придется выделить буфер для каждого имени, прежде чем вы сможете его использовать

c.filenames[0] = malloc(sizeOfString);
/* error checking */
strcpy(c.filenames[0],...

или как предложил другой плакат

c.filenames[o] = strdup(...

Первая форма может быть лучше, если вы строите свои имена файлов из нескольких частей и можете проецировать общую длину с самого начала.


{*} Позже вы можете удалить этот буфер фиксированной длины, но пока оставьте его.

1 голос
/ 30 июля 2011

В настоящее время происходит сбой, потому что вы не выделяете память для имен файлов. Или используйте strdup или malloc + strcpy (я бы использовал strdup).

Ваше поле имени файла представляет собой массив указателей на строку с нулем в конце. Вам необходимо выделить память для строки и скопировать строку в эту память. Вы сохраняете адрес новой строки в одном из указателей, например, имя_файла [0].

Код прямого адреса памяти не работает. Это просто не терпит крах, пока! Этот код просто перезаписывает массив указателей. Никогда не пишите такой код. Никогда, никогда !! Написание подобного кода морально эквивалентно употреблению в пищу маленьких единорогов.

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