#include <pwd.h>
#include <stdio.h>
struct passwd* Getpwnam_(const char* name)
{
static struct passwd* passwd;
while((passwd=getpwent())!=NULL) /* get pw entry line by line */
{
if(strcmp(passwd->pw_name, name)==0) /* find the same name */
return passwd;
}
if(passwd==NULL) /* there is no matching name */
return NULL;
}
int
main(void)
{
printf("%ld %ld\n", (long)(Getpwnam_("root")->pw_uid), (long)(Getpwnam_("cho")->pw_uid));
}
在上面的代码中,当我使用以下主要函数时:
printf("%ld\n", (long)(Getpwnam_("root")->pw_uid));
printf("%ld\n", (long)(Getpwnam_("cho")->pw_uid));
它运转良好。但是,当我使用一个带有两个printf()
的Getpwnam_()
作为参数时,我会得到一个分段错误。我认为我的代码操作没有问题。
但是,为什么这会给我一个分割错误呢??
发布于 2016-05-04 22:34:04
您需要在调用setpwent()
之间用Getpwnam_()
回滚密码数据库。
假设您的应用程序首先调用Getpwnam_("cho")
。如果在数据库中,"root"
在"cho"
之前,那么在搜索中,getpwent()
将返回"root"
,但是您的搜索将丢弃它,因为它与"cho"
不同。稍后,getpwent()
将返回"cho"
,这是有效的结果。
如果您的应用程序接下来调用Getpwnam_("root")
,那么getpwent()
将开始从上次调用中返回条目,这一点在数据库中超出了"root"
和"cho"
。由于"root"
将不再返回,搜索将不会得到结果,您将得到一个空指针,它会使程序崩溃。
发布于 2016-05-04 22:36:15
一个问题是,您试图同时保存两个密码条目。随后对getpwent
的调用可能会覆盖先前返回的信息。因此,在再次调用getpwent
之前,您需要完成返回的信息处理。如果需要,请复制所需的字段。
此外,没有必要声明指针是静态的,因为您没有返回它的地址。
( atturri提到的另一个问题是,在调用之间,您没有返回到带有setpwent
的密码的开头。如果代码在尝试引用密码字段之前检查了NULL
返回,这可能会更清楚。)
发布于 2016-05-04 22:33:49
这里的问题很可能与getpwent
返回指向它管理的(可能是静态)内存区域的指针有关。因此,基本上,当您获得返回值时,您必须在再次调用getpwent
之前使用它。因为第二次呼叫可以覆盖甚至释放由上一次呼叫返回的区域。
从手册页:
返回值可以指向一个静态区域,并且可以被随后对getpwuid()、getpwnam(3)或getpwuid(3)的调用覆盖。(不要传递返回到空闲(3)的指针。)
所以两个单独的打印可以工作,因为你使用第一个之前的第二个电话。但是,将两者放在相同的打印中意味着第二个调用将使第一个调用返回的指针无效,但是print则尝试使用这两种类型的指针。即使您没有得到一个seg错误,它也很可能不会为第一个用户产生正确的输出。
相反,您需要更改Getpwnam_,将需要的数据复制到新分配的对象中,并返回指向该对象的指针。注意:如果您也需要一些字符串,则复制将需要“递归”。
https://stackoverflow.com/questions/37043815
复制