我正在尝试将其各自节点的结构推送到共享内存中,其中另一个程序将读取节点内容以进行一些验证(只是读取,不进行修改)。链表的每个节点都包含几个变量,以及许多节点
我的结构:
typedef struct DNode {
char *polname;
char *devname;
char *status;
char *srczone;
char *dstzone;
char *srcaddr;
char *dstaddr;
char *srcuser;
char *app;
char *service;
char *urlcategory;
char *action;
char *vulnerability;
int isok;
struct DNode *next;
} Current;
struct DNode *head = NULL;
int list_insert_front(struct DNode* new_node) {
struct DNode *temp;
temp = malloc(sizeof *temp);
if (temp && new_node) {
memcpy(temp, new_node, sizeof(struct DNode));
temp->next = head;
head = temp;
return 1;
}
return 0;
}
此结构使用函数list_insert_front
从XML文件中获取数据并填充列表。此链接列表现在存储在共享内存中,以便更快地处理和轻松读取其他程序。
但是,我无法这样做(因为指针错误)。我能够向客户端发送一个易于读取的整数数据,但是当我对列表进行相同的尝试时,会发生BAM Segmentation fault
。
MAIN.C
int main(int argc, char **argv)
{
Current aaron;
Current *dlist;
int key = 5555;
int shmid;
xmlDocPtr doc;
xmlNode *root_element = NULL;
dlist = &aaron;
if (argc != 2)
{
printf("\nInvalid argument\n");
return(1);
}
doc = xmlReadFile(argv[1], NULL, XML_PARSE_NOBLANKS | XML_PARSE_NOERROR | XML_PARSE_NOWARNING | XML_PARSE_NONET);
if (doc == NULL)
{
fprintf(stderr, "Document not parsed successfully.\n");
return 0;
}
root_element = xmlDocGetRootElement(doc);
if (root_element == NULL)
{
fprintf(stderr, "empty document\n");
xmlFreeDoc(doc);
return 0;
}
printf("Root Node is %s\n", root_element->name);
traverse_dom_trees(root_element);
shmid = shmget(key, sizeof(aaron), IPC_CREAT | 0660);
if (shmid < 0) exit (1);
dlist = shmat(shmid, NULL, 0);
if (dlist == (void *) (-1))
exit(1);
printf("dlist alloc\n");
(*dlist).isok = 10;
printf("dlist val: %d\n", (*dlist).isok);
//This integer value is printed and read by the client, but not the linked list
while (Current.next != NULL){
(*dlist).polname = aaron.polname;
(*dlist).devname = aaron.devname;
(*dlist).status = aaron.status;
(*dlist).srczone = aaron.srczone;
(*dlist).dstzone = aaron.dstzone;
(*dlist).srcaddr = aaron.srcaddr;
(*dlist).dstaddr = aaron.dstaddr;
(*dlist).srcuser = aaron.srcuser;
(*dlist).app = aaron.app;
(*dlist).service = aaron.service;
(*dlist).urlcategory = aaron.urlcategory;
(*dlist).action = aaron.action;
(*dlist).vulnerability = aaron.vulnerability;
Current = Current.next;
}
printf("printing list: ");
shmdt(dlist);
xmlFreeDoc(doc);
xmlCleanupParser();
return 0;
}
我意识到我可能犯了很多愚蠢的错误,比如在while循环中,以及我尝试在共享内存段中插入结构的方式,但这就是我要求你们所有人。为了帮助我为此建立一个更好的逻辑。欢迎提出所有建议。
答案 0 :(得分:3)
您不能在共享内存段中使用指针,因为它们仅在您的进程中有效。这可能是您获得段错误的原因。您可以在共享内存段中使用偏移量。
答案 1 :(得分:3)
你展示的并不是真正的MCVE。您在结构中有13个char *
成员;对于MCVE来说,3将是充足的。您还使用XML解析函数,这些函数基本上与问题相关;你可以简化很多事情。
您不会显示将在共享内存中使用该列表的任何其他进程;拥有其中一个(它只需要附加到共享内存并遍历列表,打印结果)会很有帮助。
基本的obervation:
您明显无法确保所有数据都在共享内存中。
您的作业如:
(*dlist).polname = aaron.polname;
至少有四项伪造。首先,aaron.polname
是此进程的每进程(非共享)内存中的指针。因此,指针赋值给其他进程提供了一个伪造的地址。它指向一些随机位置,因为其他进程会占用空间 - 或者,如果您幸运的话,可以指向地址空间之外的某个位置,这样它们就会快速崩溃而不是缓慢崩溃。
其次,你还没有复制字符串;你只是分配了一个指针。这是一个问题。
第三,您将共享内存中的所有指针指向相同的位置,以便多个条目指向相同的数据。
第四,您应该使用dlist->polname
表示法。是的,你有什么工作;它不能很好地运作。检查(编写,想到)dlist->next->next
比(*(*dlist).next).next
更容易。 (我甚至不能在没有逐渐增加的情况下写出来。而且我并没有声称在这种情况下这是一个很好的表达;我只是指出链接访问更容易使用箭头ptr->member
符号而不是星点(*ptr).member
。)
您必须确保共享结构中的指针指向共享内存。
您还必须确保所有进程在同一地址加载共享内存段。如果你不能这样做,那么你根本就不能可靠地使用指针;您必须使用基址(共享内存段的起始地址)的偏移量。链接指针也需要小心处理。
您没有创建足够大的共享内存块。您正在使用:
shmid = shmget(key, sizeof(aaron), IPC_CREAT | 0660);
为一组指针创建了足够的空间,但没有空间让指针指向。您似乎也想要创建链接列表,但您只需为单个元素分配足够的空间。这必须重做。共享内存必须足够大,以包含所有共享数据 - 结构和结构指向的字符串。
所以,你需要:
dlist->polname
而不是(*dlist).polname
。