Что может быть не так с этим C в коде Unix - PullRequest
0 голосов
/ 21 марта 2012

Я довольно новичок в написании кода на C и уверен, что у меня что-то не так на самом базовом уровне.Я запускаю небольшой код для получения атрибутов файла, и эта функция ниже возвращает эти атрибуты.путь char * будет содержать что-то вроде "/ home / etc / bin"

/* copy the attributes into a character pointer */
unsigned char * copyAttributes (char *path)
{
    struct stat buf;
    stat (path, &buf);
    int nMalloc = sizeof(dev_t) + sizeof(ino_t) + sizeof(mode_t)+ sizeof(nlink_t)+ sizeof(uid_t)+ sizeof(gid_t)+ sizeof(dev_t)+ sizeof(off_t)+ sizeof(blksize_t)+ sizeof(blkcnt_t)+ sizeof(time_t)+ sizeof(time_t)+ sizeof(time_t)+ 1;
    char *pathForStatBuff = malloc(nMalloc);
    printf("%d\n",nMalloc);
    unsigned long base = 0;
    memcpy(pathForStatBuff + base,&buf.st_dev,sizeof(dev_t));
    base = base + sizeof(dev_t);    
    memcpy(pathForStatBuff + base,&buf.st_ino,sizeof(ino_t));
    base = base + sizeof(ino_t);
    memcpy(pathForStatBuff + base,&buf.st_mode,sizeof(mode_t));
    base = base + sizeof(mode_t);
    memcpy(pathForStatBuff + base,&buf.st_nlink,sizeof(nlink_t));
    base = base + sizeof(nlink_t);
    memcpy(pathForStatBuff + base,&buf.st_uid,sizeof(uid_t));
    base = base + sizeof(uid_t);
    memcpy(pathForStatBuff + base,&buf.st_gid,sizeof(gid_t));
    base = base + sizeof(gid_t);
    memcpy(pathForStatBuff + base,&buf.st_rdev,sizeof(dev_t));
    base = base + sizeof(dev_t);
    memcpy(pathForStatBuff + base,&buf.st_size,sizeof(off_t));
    base = base + sizeof(off_t);
    memcpy(pathForStatBuff + base,&buf.st_blksize,sizeof(blksize_t));
    base = base + sizeof(blksize_t);
    memcpy(pathForStatBuff + base,&buf.st_blocks,sizeof(blkcnt_t));
    base = base + sizeof(blkcnt_t);
    memcpy(pathForStatBuff + base,&buf.st_atime,sizeof(time_t));
    base = base + sizeof(time_t);
    memcpy(pathForStatBuff + base,&buf.st_mtime,sizeof(time_t));
    base = base + sizeof(time_t);
    memcpy(pathForStatBuff + base,&buf.st_ctime,sizeof(time_t));
    base = base + sizeof(time_t);   

    printf("Printing pathForStatBuff = %s\n",pathForStatBuff);
    return pathForStatBuff;
}

Печать pathForStatBuff = p 53 Печать pathForStatBuff = p 53 Печать pathForStatBuff = p 53 Печать pathForStatBuff = p 53 Печать pathForStatBuff = p 53 ПечатьpathForStatBuff = p 53 Печать pathForStatBuff = p 53 Печать pathForStatBuff = p 53 Печать pathForStatBuff = p 53 Печать pathForStatBuff = p 53 Печать pathForStatBuff = p

Это вывод, который я всегда получаю, я не могу понятьчто я делаю не такНе могли бы вы, ребята, подсказать мне, что это может быть.Спасибо.

Ответы [ 4 ]

3 голосов
/ 21 марта 2012

Вы копируете данные без каких-либо преобразований, поэтому, если оказалось, что buf.st_dev имеет наименьший значащий байт 0 (я предполагаю, что в порядке байтов), вы получите пустую строкуИз вашего примера видно, что младший бит всегда равен p (113).Вы можете попробовать использовать функцию, которой вы даете строку вместе с ее длиной, и она печатает ее в шестнадцатеричном формате, чтобы вы могли видеть данные.Вам нужно помнить разницу между числом и его десятичным представлением, число 231 не имеет ничего общего со строкой «231». В противном случае вы можете сделать что-то вроде:

sprintf(pathForStatBuf, "Dev: %d\nIno: %d\n....", buf.st_dev, buf.st_ino, ...);

Недостатком является то, чтоопределить размер буфера нелегко.

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

3 голосов
/ 21 марта 2012

Вы пытаетесь использовать двоичные данные в качестве строки. В Си строки заканчиваются нулем, что означает, что если один элемент равен нулю, то при копировании его в буфер он будет отмечать конец строки.

Если вы хотите преобразовать все данные в строку, вы должны использовать, например, snprintf вместо:

char buffer[128];
snprintf(buffer, sizeof(buffer), "%d %d %d",
         buf.st_dev, buf.st_ino, buf.st_mode);

См. Страницу руководства для snprintf для получения дополнительной информации о функции.

(В моем примере я использовал только три члена структуры, добавьте все, что вам нужно.)

1 голос
/ 21 марта 2012

Вы прекрасно копируете данные в свой блок памяти.Единственная проблема заключается в том, что вы не можете использовать printf с %s для отображения результата, потому что это не строка с нулевым символом в конце (или любая другая строка).

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

{
    int i;

    printf("Printing pathForStatBuff = { ");
    for (i = 0; i < sizeof nMalloc; i++)
        printf("%#.2x ", (unsigned char)pathForStatBuff[i]);
    printf("}\n");
}
0 голосов
/ 21 марта 2012

На первый взгляд, код:

int nMalloc = sizeof(dev_t)  + sizeof(ino_t) + sizeof(mode_t)+ ...

делает то же самое, что и

int nMalloc = sizeof(struct stat);

Редактировать: ВНИМАНИЕ - caf указала, что

int nMalloc = sizeof(dev_t)  + sizeof(ino_t) + ...

- это , а не , обязательно совпадающее с int nMalloc = sizeof(struct stat);

Поля в struct stat могут иметь ограничения на выравнивание, которые приводят к появлению «дырок» или заполнению между полями.Также могут быть недокументированные поля.Так что struct stat может быть больше, чем сумма опубликованных полей.

Это было бы несложно проверить.

if (nMalloc != sizeof(struct stat)) { fprintf(stderr, "...\n"); 

, но может измениться в будущем, поэтому ваш оригинал будет более надежным.

На основании предложения caf, это также не обязательно совпадает:

unsigned long base = 0;
memcpy(pathForStatBuff + base,&buf.st_dev,sizeof(dev_t));
base = base + sizeof(dev_t);    
...
memcpy(pathForStatBuff + base,&buf.st_ctime,sizeof(time_t));
base = base + sizeof(time_t); 

с: memcpy(pathForStatBuff, &buf, sizeof(struct stat));

, но проверка размера обнаружит это.

Таким образом, присвоение полей новой структуре позволит вам получить контроль над необходимыми полями, их порядком и некоторыми аспектами компоновки (тот же компилятор / та же платформа).

Если предпочтительнее memcpy, посмотрите на mempcpy .Это похоже на memcpy, но возвращает указатель на байт после последнего, поэтому вам не нужно делать:

p = memcpy(pathForStatBuf  + base, ...
base = base + sizeof(...)
...
base = base + sizeof(...)
p = memcpy(pathForStatBuf  + base, ...
base = base + sizeof(...)

, но вместо этого иметь дополнительный указатель и делать

p = memcpy(p, ...
p = memcpy(p, ...

Хотите получить форму для печати?Если это так, вам нужно использовать sprintf, printf или fprintf.По мере того, как вы учитесь, я конвертирую все memcpy в printf("..., buf....field ...); и сразу же их вижу, это будет проще, чем правильно получить строку в первый раз.

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