在Unix代码中这个C可能有什么问题

时间:2012-03-21 04:48:49

标签: c unix gcc

我是编写C代码的新手,我确信在最基本的层面上我有些不对劲。我正在运行一个小代码来获取文件的属性,下面的函数返回这些属性。 char * path将包含类似“/ 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 个答案:

答案 0 :(得分:3)

您正在尝试将二进制数据用作字符串。在C字符串中以零结尾,这意味着如果一个成员为零,那么当您将其复制到缓冲区时,它将标记字符串的结尾。

如果您想将所有数据转换为字符串,您应该使用例如snprintf代替:

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

有关此功能的详细信息,请参阅snprintf的手册页。

(在我的例子中,我只使用了结构的三个成员,添加了你需要的所有内容。)

答案 1 :(得分:3)

你正在复制没有变换的数据,所以如果buf.st_dev的最低有效字节为0(我假设小端),你最终会得到一个空字符串从你的例子来看,LSB看起来总是'p'(113)。你可以尝试使用一个函数,你给它提供字符串及其长度,并以十六进制打印,这样你就可以看到数据。你需要记住数字和它的十进制表示之间的差异,数字231与字符串“231”没有相似之处 否则你可以做类似的事情:

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

缺点是缓冲区大小不容易定义。

我猜你只是为了了解stat和stuff,所以你可以只分配一个大字符串(2048个字符左右),你应该保持在界限内。

答案 2 :(得分:1)

您正在将数据复制到内存块中。唯一的问题是你不能使用printf%s来显示结果,因为它不是一个以空字符结尾的字符串(或任何类型的字符串)。

如果要打印出内存块的内容以进行调试,可以用十六进制打印:

{
    int i;

    printf("Printing pathForStatBuff = { ");
    for (i = 0; i < sizeof nMalloc; i++)
        printf("%#.2x ", (unsigned char)pathForStatBuff[i]);
    printf("}\n");
}

答案 3 :(得分:0)

乍一看,代码:

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 ...);并立即查看,这比第一次获取字符串更容易。