如何正确调试用C编写的共享库?

问题描述 投票:3回答:1

我目前正在编写一个共享库,该库使用UNIX用户名并返回一个字符串,其中包含用户所属的所有组,格式为[group1, group2, group3...]

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <utmp.h>
#include <sys/types.h>
#include <grp.h>
#include <pwd.h>

int num_groups = 0;
struct passwd *pwd;
gid_t *groups;
struct group *grp;

FILE *stream;
char *buff;
size_t length;

char *printGroups(char *arg)
{
    stream = open_memstream(&buff, &length);
    pwd = getpwnam(arg);
    getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
    groups = malloc(num_groups * sizeof(gid_t));
    if (groups == NULL){
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    getgrouplist(arg, pwd->pw_gid, groups, &num_groups);
    fprintf(stream, " [");
    for (int i = 0; i < num_groups; ++i){
        grp = getgrgid(groups[i]);
        if (i == num_groups - 1)
            fprintf(stream, "%s", grp->gr_name);
        else
            fprintf(stream, "%s ", grp->gr_name);
    }
    free(groups);
    fprintf(stream, "]");
    fclose(stream);
    return buff;
}

这是我的共享库中返回字符串的主要功能。我验证了该功能确实是正确的 - 相同的逻辑在使用printf而不是open_memstream stringstream的独立程序中工作。

但是这个库有段错误,我无法确定原因。 Valgrind没有输出任何有用的东西:

gcc -shared -fpic -g -Wall lib.c valgrind ./a.out == 9916 ==使用信号11(SIGSEGV)的默认操作终止进程 == 9916 ==不在地址0x0的映射区域内访问 == 9916 ==在0x1:??? == 9916 == by 0xFFF000672:???

gdb backtrace也是如此:

程序接收信号SIGSEGV,分段故障。 0x0000000000000001在?? ?? ()(gdb)回溯 在#?? 0x0000000000000001? () #1 0x00007fffffffe6e9在? () 在#?? 0x0000000000000000? ()

我没有想法。有人能指出我的解决方案,在.so源中出现错误,或者Valgrind和gdb打印的原因是什么?尽管在编译时使用-g标志?

c linux gcc gdb valgrind
1个回答
3
投票

您似乎正在尝试直接运行共享库。这不是共享库的工作方式。它们被其他使用它们的程序引用。

例如,此代码将使用您的库:

#include <stdio.h>
#include <stdlib.h>

char *printGroups(char *);

int main()
{
    char *groups = printGroups("root");
    printf("groups: %s\n", groups);
    free(groups);
    return 0;
}

如果你第一次编译你的库像这样:

gcc -shared -fpic -g -Wall lib.c -o libmylib.so

然后,假设此库与上述测试代码位于同一目录中,则编译测试代码,如下所示:

gcc -g -Wall -Wextra -L. -o mytest mytest.c -lmylib

然后设置一个环境变量来查找您的库:

export LD_LIBRARY_PATH=.

然后,您可以运行将使用您的库的测试程序。

© www.soinside.com 2019 - 2024. All rights reserved.