我正在编写一个程序,用于存储带有链接结构的主题列表。该程序从文件中读取主题列表,并创建第一个主题“metatema”,然后创建文件中的主题。 当我在文件中写入4个或5个主题时,它可以正常工作。但是当我写更多主题并打印值时,我得到的值不正确。
以下是我的计划的相关代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#define BUFFER_SIZE 256
/* STRUCTS */
typedef struct user {
struct sockaddr * direccion; /* Dir from user */
struct user * siguiente; /* Next user node */
};
typedef struct topic {
char * nombre; /* Topic name */
int numero_usuarios; /* Number of users */
struct user * lista; /* Pointer to the users list */
struct topic * siguiente; /* Next topic */
};
/* GLOBAL VARs */
int numero_temas = 0;
struct topic * temas;
int tam_topic = 0;
int tam_user = 0;
/* FUNCTIONS */
void leerTemas(char * file);
int main(int argc, char *argv[]) {
if (argc!=3) {
fprintf(stderr, "Use: %s port file\n", argv[0]);
return 1;
}
leerTemas(argv[2]);
/* PRINT VALUES */
int i=0;
for(i=0; i<numero_temas;i++){
printf("TOPIC: %s\tADDRESS: %u",(temas + i*sizeof(struct topic))->nombre,(temas + i*sizeof(struct topic)));
printf("\tNEXT: %u\tUSERS LIST: %u\t NUM. USERS: %u\n",(temas + i*sizeof(struct topic))->siguiente,
(temas + i*sizeof(struct topic))->lista, (temas + i*sizeof(struct topic))->numero_usuarios);
}
return 0;
}
void leerTemas(char * file){
int pipefd[2];
if(pipe(pipefd) == -1){
perror("pipe");
exit(1);
}
/* CALCULAMOS EL NUMERO DE TEMAS PARA RESERVAR MEMORIA */
numero_temas = 0;
switch(fork()){
case -1: // ERROR
perror("fork");
exit(1);
case 0: // CHILD (WC)
close(pipefd[0]);
close(1);
dup(pipefd[1]);
close(pipefd[1]);
execlp("wc","wc",file,(char *)NULL);
perror("exec");
exit(1);
default: // PARENT (GET RESULT FROM WC)
close(pipefd[1]);
char buffer[BUFFER_SIZE]; bzero(buffer,BUFFER_SIZE);
char ntemas[BUFFER_SIZE]; bzero(ntemas,BUFFER_SIZE);
if(read(pipefd[0],buffer,BUFFER_SIZE) <= 0){
perror("read");
exit(1);
}
/* GETTING THE NUMBER OF LINES FROM WC */
int i=0,j=0;
while(buffer[i] == ' ') // Pass blank spaces
i++;
while(buffer[i] != ' '){
ntemas[j] = buffer[i];
i++;
j++;
}
ntemas[j] = '\0';
numero_temas = atoi(ntemas)+1; // +1 (metatema)
}
/* ALLOCATING TOPICs MEMORY */
temas = malloc(sizeof(struct topic) * numero_temas);
bzero(temas,sizeof(struct topic)*numero_temas);
/* CREATING METATEMA */
temas->nombre = malloc(sizeof(char)*9);
strcpy(temas->nombre,"metatema\0");
temas->siguiente = NULL;
temas->lista = NULL;
temas->numero_usuarios = 0;
/* CREATING TOPICs FROM FILE */
FILE * f = fopen(file,"r");
int i;
char buffer[BUFFER_SIZE];
for(i = 1; i < numero_temas; i++){
bzero(buffer,BUFFER_SIZE);
fgets(buffer,BUFFER_SIZE,f);
buffer[strlen(buffer)-1] = '\0'; // Remove newline char \n
(temas + i*sizeof(struct topic))->nombre = malloc(sizeof(char)*(strlen(buffer)+1));
strcpy((temas+i*sizeof(struct topic))->nombre,buffer);
(temas + i*sizeof(struct topic))->numero_usuarios = 0;
(temas + i*sizeof(struct topic))->lista = NULL;
(temas + i*sizeof(struct topic))->siguiente = NULL;
(temas + (i-1)*sizeof(struct topic))->siguiente = (temas + i*sizeof(struct topic)); // Link prev topic
}
}
当我在文件中运行包含5个主题的程序时运行正常:
$ cat topics
topic1
topic2
topic3
topic4
topic5
$ ./a.out 8000 topics
TOPIC: metatema ADDRESS: 31891472 NEXT: 31892496 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic1 ADDRESS: 31892496 NEXT: 31893520 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic2 ADDRESS: 31893520 NEXT: 31894544 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic3 ADDRESS: 31894544 NEXT: 31895568 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic4 ADDRESS: 31895568 NEXT: 31896592 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic5 ADDRESS: 31896592 NEXT: 0 USERS LIST: 0 NUM. USERS: 0
但是,当我设置7个主题(例如)时,我得到了错误的值:
$ cat topics
topic1
topic2
topic3
topic4
topic5
topic6
topic7
$ ./a.out 8000 topics
TOPIC: metatema ADDRESS: 7274512 NEXT: 7275536 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic1 ADDRESS: 7275536 NEXT: 7276560 USERS LIST: 1768976244 NUM. USERS: 33
TOPIC: topic2 ADDRESS: 7276560 NEXT: 7277584 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic3 ADDRESS: 7277584 NEXT: 7278608 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic4 ADDRESS: 7278608 NEXT: 7279632 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic5 ADDRESS: 7279632 NEXT: 7280656 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic6 ADDRESS: 7280656 NEXT: 7281680 USERS LIST: 0 NUM. USERS: 0
TOPIC: topic7 ADDRESS: 7281680 NEXT: 0 USERS LIST: 0 NUM. USERS: 0
而且,当我设置11个主题时,我明白了:
$cat topics
topic1
topic2
topic3
topic4
topic5
topic6
topic7
topic8
topic9
topic0
topicA
$ ./a.out 8000 topics
a.out: malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end & pagemask) == 0)' failed.
Abortado
我做错了什么?
答案 0 :(得分:4)
这是问题
(temas + i*sizeof(struct topic))
编译器会自动为您计算偏移量,即
(temas + i)
是您所需要的,或
((char *)temas + i*sizeof(struct topic))
因为这样编译器不会将i
乘以sizeof(struct topic)
,但在之前的情况下它会使代码实际意味着
((char *)temas + i*sizeof(struct topic)*sizeof(struct topic))
所以你添加的东西比你想要的多得多,你不需要像这样使用指针算法,只需
temas[i]
就足够了。
此外,绝对不需要全局变量,只需将它们作为函数参数传递,全局变量可能会导致很多问题,除非您完全确定需要,否则不应使用它们。