指向相同内存地址的结构指针产生不同的数据?
struct pointers to same memory address producing different data?
我有这个简单的代码来读取文件的行并将它们存储在结构中:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct filedata {
char **items;
int lines;
};
struct filedata *read_file(char *filename) {
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("Can't read %s \n", filename);
exit(1);
}
char rbuff;
int nlines = 0; // amount of lines
int chr = 0; // character count
int maxlen = 0; // max line length (to create optimal buffer)
int minlen = 2; // min line length (ignores empty lines with just \n, etc)
while ((rbuff = fgetc(file) - 0) != EOF) {
if (rbuff == '\n') {
if (chr > maxlen) {
maxlen = chr + 1;
}
if (chr > minlen) {
nlines++;
}
chr = 0;
}
else {
chr++;
}
}
struct filedata *rdata = malloc(sizeof(struct filedata));
rdata->lines = nlines;
printf("lines: %d\nmax string len: %d\n\n", nlines, maxlen);
rewind(file);
char *list[nlines];
int buffsize = maxlen * sizeof(char);
char buff[buffsize];
int i = 0;
while (fgets(buff, buffsize, file)) {
if (strlen(buff) > minlen) {
list[i] = malloc(strlen(buff) * sizeof(char) + 1);
strcpy(list[i], buff);
i++;
}
}
rdata->items = (char **)list;
fclose(file);
int c = 0;
for (c; c < rdata->lines; c++) {
printf("line %d: %s\n", c + 1, rdata->items[c]);
}
printf("\n");
return rdata;
}
int main(void) {
char fname[] = "test.txt";
struct filedata *ptr = read_file(fname);
int c = 0;
for (c; c < ptr->lines; c++) {
printf("line %d: %s\n", c + 1, ptr->items[c]);
}
return 0;
}
这是我 运行 时的输出:
lines: 2
max string len: 6
line 1: hello
line 2: world
line 1: hello
line 2: H��
出于某种原因,当它到达 ptr->items 中的第二个索引时,它会打印乱码输出。但是,如果我在那里放一些 printf() 来显示指针地址,它们是完全一样的。
Valgrind 在第二次遍历 char 数组时也会打印:
==3777== Invalid read of size 8
==3777== at 0x400AB3: main (test.c:81)
==3777== Address 0xfff000540 is on thread 1's stack
==3777== 240 bytes below stack pointer
但这并没有给我任何线索。
如果重要的话,我正在使用 gcc 4.9.4 和 glibc-2.24。
list
是一个非静态局部变量,在退出其范围后使用它(在这种情况下从 read_file
返回)将调用 未定义的行为因为它会在退出其范围时消失。动态分配它(通常在堆上),如
char **list = malloc(sizeof(char*) * nlines);
添加代码以检查 malloc()
是否成功将使您的代码更好。
变量 list
是 read_file
的局部变量,但您在 rdata->items
中存储了指向 list
的指针。当read_file
returns时,rdata->items
是一个悬垂指针,访问它是未定义的行为。
我有这个简单的代码来读取文件的行并将它们存储在结构中:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct filedata {
char **items;
int lines;
};
struct filedata *read_file(char *filename) {
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("Can't read %s \n", filename);
exit(1);
}
char rbuff;
int nlines = 0; // amount of lines
int chr = 0; // character count
int maxlen = 0; // max line length (to create optimal buffer)
int minlen = 2; // min line length (ignores empty lines with just \n, etc)
while ((rbuff = fgetc(file) - 0) != EOF) {
if (rbuff == '\n') {
if (chr > maxlen) {
maxlen = chr + 1;
}
if (chr > minlen) {
nlines++;
}
chr = 0;
}
else {
chr++;
}
}
struct filedata *rdata = malloc(sizeof(struct filedata));
rdata->lines = nlines;
printf("lines: %d\nmax string len: %d\n\n", nlines, maxlen);
rewind(file);
char *list[nlines];
int buffsize = maxlen * sizeof(char);
char buff[buffsize];
int i = 0;
while (fgets(buff, buffsize, file)) {
if (strlen(buff) > minlen) {
list[i] = malloc(strlen(buff) * sizeof(char) + 1);
strcpy(list[i], buff);
i++;
}
}
rdata->items = (char **)list;
fclose(file);
int c = 0;
for (c; c < rdata->lines; c++) {
printf("line %d: %s\n", c + 1, rdata->items[c]);
}
printf("\n");
return rdata;
}
int main(void) {
char fname[] = "test.txt";
struct filedata *ptr = read_file(fname);
int c = 0;
for (c; c < ptr->lines; c++) {
printf("line %d: %s\n", c + 1, ptr->items[c]);
}
return 0;
}
这是我 运行 时的输出:
lines: 2
max string len: 6
line 1: hello
line 2: world
line 1: hello
line 2: H��
出于某种原因,当它到达 ptr->items 中的第二个索引时,它会打印乱码输出。但是,如果我在那里放一些 printf() 来显示指针地址,它们是完全一样的。
Valgrind 在第二次遍历 char 数组时也会打印:
==3777== Invalid read of size 8
==3777== at 0x400AB3: main (test.c:81)
==3777== Address 0xfff000540 is on thread 1's stack
==3777== 240 bytes below stack pointer
但这并没有给我任何线索。
如果重要的话,我正在使用 gcc 4.9.4 和 glibc-2.24。
list
是一个非静态局部变量,在退出其范围后使用它(在这种情况下从 read_file
返回)将调用 未定义的行为因为它会在退出其范围时消失。动态分配它(通常在堆上),如
char **list = malloc(sizeof(char*) * nlines);
添加代码以检查 malloc()
是否成功将使您的代码更好。
变量 list
是 read_file
的局部变量,但您在 rdata->items
中存储了指向 list
的指针。当read_file
returns时,rdata->items
是一个悬垂指针,访问它是未定义的行为。